一个典型的ELF可重定位目标文件的格式如图1:
图1 典型的ELF可重定位目标文件
图2 可执行文件的存储器映像
ELF头以一个16字节的序列开始,描述了生成该文件的系统的字的大小和字节顺序。ELF头剩下的部分包含帮助连接器语法分析和解释目标文件的信息。其中包括ELF头的大小、目标文件的类型(如可重定位、可执行、共享的)、机器类型(如x86-64)、节头部表的文件偏移,以及节头部表中条目的大小和数量。
.text
已编译程序的机器代码
.rodata
只读数据
.data
已初始化的全局和静态C变量。局部C变量在运行时被保存在栈中,既不出现在.data节中,也不出现在.bss节中。
.bss
未初始化的全局和静态C变量,以及所有被初始化为0的全局或静态变量。在目标文件中这个节不占据实际的空间,它仅仅是一个占位符。目标文件格式区分已初始化和未初始化变量是为了空间效率:在目标文件中,未初始化变量不需要占据任何实际的磁盘空间。运行时,在内存中分配这些变量,初始值为0.
$ readelf -h HelloWorld
ELF Header:
Magic: 7f 45 4c 46 02 01 01 03 00 00 00 00 00 00 00 00 魔数
Class: ELF64 分类
Data: 2's complement, little endian 数据表示:补码、小端
Version: 1 (current) 版本号
OS/ABI: UNIX – Linux Linux的ABI
ABI Version: 0 ABI版本
Type: EXEC (Executable file) 类型:可执行文件
Machine: Advanced Micro Devices X86-64 硬件平台:AMD x86-64
Version: 0x1 版本号
Entry point address: 0x4003e0 程序入口地址
Start of program headers: 64 (bytes into file) 程序头表的位置
Start of section headers: 2472 (bytes into file) 节头表的位置
Flags: 0x0 标志
Size of this header: 64 (bytes) 文件头的大小:64字节
Size of program headers: 56 (bytes) 程序头表项的大小:56字节
Number of program headers: 8 程序头表项的数目:8项
Size of section headers: 64 (bytes)
Number of section headers: 30 节头表项的大小30字节
Section header string table index: 27 节头表的项数目:27项
.symtab 节
符号表
过程和静态变量名
节名和位置
.rel.text 节文本部分的重新定位信息
在可执行文件中需要修改的指令的地址
修改指令
.rel.data 节数据段的重新定位信息
在合并的可执行文件中需要修改的指针数据的地址
.debug 节符号调试信息(gcc -g)
.line
初始C源程序中的行号和.text节中机器指令之间的映射。只有以-g选项调用编译器驱动程序时,才会得到这张表。
.srttab
一个字符串表
以null结尾的字符串序列
节头表每节的偏移和大小
PS:为什么未初始化的数据称为.bss ?
用术语.bss来表示未初始化的数据是很普遍的,它起始于IBM704汇编语言中“块存储开始(Block Storage Start)”指令的首字母缩写,并沿用至今。一种记住.bata和.bss节之间区别的简单方法是吧“bss”看成是"更好的节省空间(Better Save Space)"的缩写。
本篇内容出自《深入理解计算机系统》第三版的第七章 链接 的 7.4可重定位目标文件
原著《Computer Systems A Programmer's Perspective Third Edition》【美】Randal E.Bryant 【美】David R.O'Hallaron