C/C++ 链接相关概念整理

 

链接通常是从一个文本文件到一个可执行文件的最后一步,本文梳理了链接过程中出现的部分关键概念

  1. 链接 linking : 将多个目标文件和库文件链接成一个可执行文件的过程;
  2. 编译器驱动程序 compiler driver : 负责调用预处理器编译器汇编器链接器;
  3. 预处理器 preprocessor : 处理以 # 开头的预处理指令, 将 #include 的文件插入到源文件中, 生成一个扩展名为 .i 的文件;
  4. 编译器 compiler : 将预处理后的.i 文件转换成扩展名为 .s 的汇编语言文件;
  5. 汇编器 assembler : 将汇编语言文件转换成机器语言指令, 生成一个扩展名为 .o 的可重定位目标文件;
  6. 链接器 linker : 将多个可重定位目标文件和库文件链接成一个可执行目标文件, 生成一个扩展名为 .out 的可执行文件,完成符号解析重定位两个主要任务;
  7. 加载器 loader : 将可执行文件中的代码和数据加载到内存中, 并执行可执行文件中的 main 函数;
  8. 符号 symbol : 函数、全局变量和静态变量的名字;
  9. 强符号 strong symbol : 函数和初始化的全局变量是强符号;
  10. 弱符号 weak symbol : 未初始化的全局变量是弱符号;
  11. 符号解析 symbol resolution : 链接器将每个符号引用与一个符号定义关联起来(理解引用和定义是否在同一文件中的解析方法、如何解析多重定义的全局符号、如何用静态库来解析符号);
  12. 全局符号 global symbol : 可以被其他文件访问的符号,全局链接器符号对应于非静态函数和非静态全局变量;
  13. 外部符号 external symbol : 可以被文件访问的其他文件符号,外部链接器符号对应于非静态函数和非静态全局变量;
  14. 局部符号 local symbol : 只能被定义的文件访问的符号,局部链接器符号对应于静态函数和静态全局变量;
  15. 符号表 symbol table : 保存了函数和全局变量的定义和引用的信息;
  16. 目标文件 object file : 包括可重定位目标文件可执行目标文件共享目标文件;
  17. 可重定位目标文件 relocatable object file : 二进制代码和数据, 可以在链接时与其他可重定位目标文件合并, 创建一个可执行目标文件;
  18. 可执行目标文件 executable object file : 二进制代码和数据, 可以被加载到内存中, 由系统执行;
  19. 共享目标文件 shared object file : 一种特殊的可重定位目标文件, 可以在加载或者运行时被动态加载进内存并链接;
  20. 可执行可链接格式 ELF : 一种用于现代 x86-64 Linux 系统的描述目标文件格式的标准;
  21. 静态库 static library : 一组可重定位目标文件的集合,通过 AR 工具将多个可重定位目标文件打包成一个文件,链接时, 链接器只复制程序中引用的目标文件中的函数和全局变量, 而不是复制整个静态库;
  22. 存档 archiver : 静态库的文件格式, 一组可重定位目标文件的集合, 它们被归档在一个文件中, 通常以 .a 为扩展名;
  23. 重定位 relocation :把每一个符号定义与一个内存位置关联起来,然后修改所有对这个符号的引用,使得它们指向这个内存位置;
  24. 重定位条目 relocation entry : 重定位表中的每个条目都描述了一个需要修改的引用的位置和如何修改的信息;
  25. 代码段 text segment : 包含程序的机器代码, 通常是只读的,包含.text 和.rodata 节,从地址 0x400000 开始;
  26. 数据段 data segment : 包含已初始化的全局和静态 C 变量,包含.data 和.bss 节;
  27. 堆 heap : 在数据段之后,从低地址向高地址增长,由用户分配和释放;
  28. 栈 stack : 从高地址向低地址增长,由编译器自动分配和释放;
  29. 动态链接 dynamic linking : 在程序运行的时候才将共享库中的代码和数据链接到进程的地址空间中, 通常以 .so 为扩展名;
ELF 格式 描述
ELF 头部 描述该文件的大小字节顺序、目标文件类型(可重定位、可共享、可执行)、机器类型节头部表的文件偏移等信息
.text 节 包含程序的机器代码
.rodata 节 包含只读数据
.data 节 包含已初始化的全局和静态 C 变量
.bss 节 包含未初始化的全局和静态 C 变量 ,不占用实际空间,只是一个占位符
.symtab 节 符号表 ,它保存了函数和全局变量的定义和引用的信息
.rel.text 节 包含.text 节中需要被重定位的引用
.rel.data 节 包含.data 节中需要被重定位的引用
.debug 节 包含调试符号表,它保存了程序中定义的局部变量类型定义的信息 ,只有以 -g 选项编译时才会生成该节
.line 节 包含行号和.text 节中机器指令的对应关系 ,只有以 -g 选项编译时才会生成该节
.strtab 节 包含字符串表,它保存了符号表中的字符串
节头部表 包含了 ELF 文件中所有节的位置和大小 ,它的大小和位置由 ELF 头部中的 e_shentsize 和 e_shoff 决定
符号表条目 描述
int name 字符串表中的字节偏移量
long value 符号的地址,对于可重定位目标文件,它是相对于节的偏移量,对于可执行目标文件和共享目标文件,它是绝对地址
int size 符号的大小
char type 符号的类型
char binding 表示符号是局部的还是全局的
short section 符号所在节的索引