目录
一:可重定位目标文件的特点
•可被链接(合并)生成可执行文件或共享目标文件
•静态链接库文件由若干个可重定位目标文件组成
•包含代码、数据(已初始化全局变量和局部静态变量.data和未初始化的全局变量和局部静态变量.bss)
•包含重定位信息(指出哪些符号引用处需要重定位)
•文件扩展名为.o(相当于Windows中的.obj文件)
我们都知道可重定位目标文件都是用来进行链接生成可执行目标文件的,那么下面我们来看下相应的链接试图,看看可重定位目标文件中都包含什么信息,下图是一个简单的举例,一起来看下吧。
通过上面的图片我们可以看出ELF文件主要包含了text,data,bss节,之前的文章对这些节的内容也做了简单的介绍,具体可以翻看之前的内容。要想进行连接,除了这几个节之前还需要其他的信息,比如符号表,重定位信息等等,这些后面会一一介绍。这里我们先介绍下为什么会有BSS节。
•C语言规定:
– 未初始化的全局变量和局部静态变量的默认初始值为0
• 将未初始化变量(.bss节)与已初始化变量(.data节)分开的好处
– .data节中存放具体的初始值,需要占磁盘空间
– .bss节中无需存放初始值,只要说明.bss中的每个变量将来在执行时占用几个字节即可,
因此,.bss节实际上不占用磁盘空间,提高了磁盘空间利用率
• BSS 中所用的一个 (Block Started by Symbol)最初是UA-SAP汇编程序伪指令,用于为符号预留一块内存空间
• 所有 通过专门的 未初始化的全局变量和局部静态变量 “节头表(Section header table)”
都被汇总到.bss节中,来说明应该为.bss节预留多大的空间
二:可重定位目标文件的格式
上面讲了可重定位目标文件有text,data,bss节,除了这些内容还有其他的重要信息,下面我们一起来探讨一下吧。
从上面的图中我们可以看到可执行目标文件包含的内容有很多,下面我们一一进行分析
1:ELF头
ELF头位于ELF文件开始,包含文件结构说明信息。分32位系统对应结构和64位系统对应结构(32位版本、64位版本)。包括16字节标识信息、文件类型 (.o,exec, .so)、机器类型(如 IA-32)、节头表的偏移、节头表的表项大小以及表项个数。
我们以32为操作系统做举例,其对应的数据结构如下所示:
#define EI_NIDENT 16
typedef struct { unsigned char e_ident[EI_NIDENT];
Elf32_Half e_type;
Elf32_Half e_machine;
Elf32_Word e_version;
Elf32_Addr e_entry;
Elf32_Off e_phoff;
Elf32_Off e_shoff;
Elf32_Word e_flags;
Elf32_Half e_ehsize;
Elf32_Half e_phentsize;
Elf32_Half e_phnum;
Elf32_Half e_shentsize;
Elf32_Half e_shnum;
Elf32_Half e_shstrndx;
} Elf32_Ehdr;
定义了ELF魔数、版本、小端/大端、操作系统平台、目标文件的类型、机器结构类型、程序执行的入口地址、程序头表(段头表)的起始位置和长度、节头表的起始位置和长度等
其中魔数在文件开头的几个字节中,通常是用来确定 文件的类型和格式的,加载或读取文件的时候可以用魔数来确定文件的类型是否正确。
a.out的魔数:01H 07H
PE格式魔数:4DH 5AH
2:.text 节
编译后的代码部分
3:.rodata 节
只读数据,如 printf 格式串、switch跳转表等
4:.data 节
已初始化的全局变量
5:.bss 节
未初始化全局变量,仅是占位符,不占据任何实际磁盘空间。区分初始化和非初始化是为了空间效率
6:.symtab 节
存放函数和全局变量 (符号表)信息 ,它不包括局部变量
7:.rel.text 节
.text节的重定位信息,用于重新修改代码段的指令中的地址信息
8:.rel.data 节
.data节的重定位信息,用于对被模块使用或定义的全局变量进行重定位的信息
9:.debug 节
调试用符号表 (gcc -g)
10:strtab 节
包含symtab和debug节中符号及节名Section header table(节头表)每个节的节名、偏移和大小
11:Section header table(节头表)
每个节的节名、偏移和大小
上面这些就是可重定位目标文件包含的信息了,其中Section header table(节头表)表述就是每个节所占据的地址空间大小了。
上图中就是节头表的信息举例,使用readelf -S test.o命令可以查看,其中Addr例表述的是每个节映射到虚拟地址的位置,因为可重定位目标文件还没有经过链接过程,所以该例都是0,经过链接过程之后才会将各个节映射到虚拟地址上去。
上述各个节中有4个节会被分配存储空间,其他的节在系统真正运行的时候是不会分配存储空间的。
.text:可执行
.data和.bss:可读可写
.rodata:可读