深入理解计算机系统(第三版)/ CSAPP 杂谈,第7章:链接

  • 链接器主要完成符号解析和重定位两个任务。

  • 目标文件有三种形式:可重定位目标文件(.so);可执行目标文件(.exe),共享目标文件(.so)。

  • linux x86-64 的可重定位目标文件使用 ELF 格式。ELF 头的前 16 字节描述文件对应系统的字的大小和字节顺序,后面还有头的大小,目标文件类型,机汽类型,各 section header 的文件偏移,以及它们的大小和数量。

  • 一般 ELF 包含以下几种 section:

    • .text:可执行机器码
    • .rodata:只读数据,如字符串常量和 switch 跳转表
    • .data:已初始化的全局和静态变量
    • :bss:未初始化或初始化为 0 的全局和静态变量。不占空间,仅仅为占位符。运行时在内存动态生成。
    • .symtab:符号表,存放定义和引用的函数与全局变量的信息。使用 STRIP 命令可以去掉符号表。
    • .rel.text:.text 中位置的列表,是重定位信息。链接器把目标文件组合起来的时候,需要修改这些位置,以让各个目标文件链接起来。一般来说,修改的是外部函数或者引用全局变量的位置,调用的本地函数的位置则不需要修改。
    • .rel.data: 引用或定义的所有全局变量的重定位信息。
    • .debug:调试符号表。用 -g 选项编译的时候才会得到这张表。
    • .line:源程序的行号与 .text 机器码的对应关系。用 -g 选项编译的时候才会得到这张表。
    • .strtab:字符串表,包括 .symtab,.debug,节头名字。以 null 结尾的字符串序列。

—- 2018.12.14 —-

  • .symtab 存储各 section 重定位信息

  • 弱全局符号是未赋值的全局符号,会被强全局符号覆盖,包括类型,所以容易导致类型不匹配的细微的bug;强全局符号是初始化的全局符号,会互相冲突。弱全局符号分配在 COMMON section 中,强全局符号分配在 .bss 中。

  • 静态库用于共享重复的代码,链接器仅会拷贝需要的函数。也可以通过参数拷贝所有函数。

  • gcc 的静态库链接是按顺序进行的。遇到目标文件 .o 时会把未定义和已定义的符号保存起来,遇到存档文件 .a 时,除了前面的操作,还会把 .a 的成员符号与未定义的符号比较,把匹配的成员符号对应的 .o 链接起来。这样的话因为是顺序的,如果把静态库放在前面,则会错过后面目标文件的匹配,从而在链接完所有文件,却还是有未定义符号,结果编译报错。

  • 所以一般做法是静态库文件放在最后。如果 .a 库相互之间也有依赖,则需要将 .a 库排序。

版权所有,转载请注明出处:
https://sickworm.com/?p=500

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据