目标文件的格式

  • 目标文件:源码编译后但还未链接的文件
  • 在linux平台下目标文件可执行文件动态链接库静态链接库具有相似的文件结构,统称为ELF文件,在windows平台下是PE-COFF格式

目标文件的构成

  • ELF文件由文件头、代码段(.text)、数据段(.data)及.bss段,具体作用见下图

  • 未初始化的全局变量局部静态变量默认值都为0,故没必要放在.data

  • .bss段只是为未初始化的全局变量和局部静态变量预留位置,并没有内容,在文件中不占用空间(仅需记录预留位置的大小)

  • 数据和代码分离的好处

    • 权限保护。指令区设置为只读, 数据区可读写
    • 提高缓存命中率
    • 便于资源分隔与共享

举例&工具

  • 测试代码

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    int printf(const char *format, ...);
    int global_init_var = 84; //.data段
    int global_uninit_var;

    void func1(int i)
    {
    printf("%d\n", i);
    }

    int main(void)
    {
    static int static_var = 85; //.data段
    static int static_var2;
    int a = 1;
    int b;
    func1(static_var + static_var2 + a + b);
    return a;
    }
  • 编译: gcc -c test.c -o test.o

  • 查看段大小:size test.o

  • 查看各段简短信息:objdump -h test.o

  • 查看各段详细信息:objdump -s -x -d test.o

    如下.data段存储的global_init_varstatic_var两个值,对应16进制0x54和0x55

1
2
Contents of section .data:
0000 54000000 55000000 T...U...
  • 使用objcopy将一个二进制文件写入一个elf文件段内
    1
    objcopy -I binary -O elf64-x86-64 -B i386 test.jpeg test.o
  • 在代码中指定变量或函数存储的段
    1
    2
    __attribute__((section("FOO"))) int global = 42;
    __attribute__((section("BAR"))) void foo(){}