- 出版者的话
- 中文版序一
- 中文版序二
- 译者序
- 前言
- 关于作者
- 第 1 章:计算机系统漫游
- 第 2 章:信息的表示和处理
- 第 3 章:程序的机器级表示
- 第 4 章:处理器体系结构
- 第 5 章:优化程序性能
- 第 6 章:存储器层次结构
- 第 7 章:链接
- 第 8 章:异常控制流
- 第 9 章:虚拟内存
- 第 10 章:系统级 I/O
- 第 11 章:网络编程
- 第 12 章:并发编程
- 附录 A:错误处理
- 实验 1:Data Lab
- 实验 3:Attack Lab
- 实验 4:Architechture Lab
- 实验 5:Cache Lab
- 实验 6:Performance Lab
- 实验 7:Shell Lab
- 实验 8:Malloc Lab
- 实验 9:Proxy Lab
文章来源于网络收集而来,版权归原创者所有,如有侵权请及时联系!
7.4 可重定位目标文件
图 7-3 展示了一个典型的 ELF 可重定位目标文件的格式。ELF 头(ELF header)以一个 16 字节的序列开始,这个序列描述了生成该文件的系统的字的大小和字节顺序。ELF 头剩下的部分包含帮助链接器语法分析和解释目标文件的信息。其中包括 ELF 头的大小、目标文件的类型(如可重定位、可执行或者共享的)、机器类型(如 X86-64)、节头部表(section header table)的文件偏移,以及节头部表中条目的大小和数量。不同节的位置和大小是由节头部表描述的,其中目标文件中每个节都有一个固定大小的条目(entry)。
夹在 ELF 头和节头部表之间的都是节。一个典型的 ELF 可重定位目标文件包含下面几个节:
- .text:已编译程序的机器代码。
- .rodata:只读数据,比如 printf 语句中的格式串和开关语句的跳转表。
- .data:已初始化的全局和静态 C 变量。局部 C 变量在运行时被保存在栈中,既不岀现在 .data 节中,也不岀现在 .bss 节中。
- .bss:未初始化的全局和静态 C 变量,以及所有被初始化为 0 的全局或静态变量。在目标文件中这个节不占据实际的空间,它仅仅是一个占位符。目标文件格式区分已初始化和未初始化变量是为了空间效率:在目标文件中,未初始化变量不需要占据任何实际的磁盘空间。运行时,在内存中分配这些变量,初始值为 0。
- .symtab:一个符号表,它存放在程序中定义和引用的函数和全局变量的信息。一些程序员错误地认为必须通过 -g 选项来编译一个程序,才能得到符号表信息。实际上,每个可重定位目标文件在 .symtab 中都有一张符号表(除非程序员特意用 STRIP 命令去掉它)。然而,和编译器中的符号表不同,.symtab 符号表不包含局部变量的条目。
- .rel.text:一个 .text 节中位置的列表,当链接器把这个目标文件和其他文件组合时,需要修改这些位置。一般而言,任何调用外部函数或者引用全局变量的指令都需要修改。另一方面,调用本地函数的指令则不需要修改。注意,可执行目标文件中并不需要重定位信息,因此通常省略,除非用户显式地指示链接器包含这些信息。
- .rel.data:被模块引用或定义的所有全局变量的重定位信息。一般而言,任何已初始化的全局变量,如果它的初始值是一个全局变量地址或者外部定义函数的地址,都需要被修改。
- .debug:一个调试符号表,其条目是程序中定义的局部变量和类型定义,程序中定义和引用的全局变量,以及原始的 C 源文件。只有以 - g 选项调用编译器驱动程序时,才 会得到这张表。
- .line:原始 C 源程序中的行号和 .text 节中机器指令之间的映射。只有以 -g 选项调用编译器驱动程序时,才会得到这张表。
- .strtab:一个字符串表,其内容包括 .symtab 和 .debug 节中的符号表,以及节头部中的节名字。字符串表就是以 null 结尾的字符串的序列。
旁注 - 为什么未初始化的数据称为 .bss
用术语 .bss 来表示未初始化的数据是很普遍的。它起始于 IBM 704 汇编语言(大约在 1957 年)中“块存储开始(Block Storage Start)”指令的首字母缩写,并沿用至今。一种记住 .data 和 .bss 节之间区别的简单方法是把 “bss” 看成是“更好地节省空间(Better Save Space)” 的缩写。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论