Chapter 7 链接

静态链接

  • 符号解析
  • 重定位
    • 编译器和汇编器生成.text和.data
    • 链接器通过把每个符号定义和一个内存位置关联,对这些节进行重定位;修改引用,让符号指向这个内存位置

可重定位目标文件

  • .rel.*:不同节的重定位信息
  • .line:原始C程序和.text节中机器指令的映射,”-g”得到

  • .bss:未初始化的静态变量,以及初始化为0的全局或静态变量
  • COMMON:未初始化的全局变量

解析多重定义符号

  • 不允许有多个同名的强符号(定义并初始化)
  • 强弱同在,选强符号
  • 只有弱符号,随便选一个弱符号

重定位

  • 重定位节和符号定义
    • 将相同类型的节合并为同一类型的新的聚合节
    • 每条指令和全局变量有唯一的运行时内存地址
  • 重定位节的符号引用
    • 修改代码节和数据节中的对符号的引用,指向正确的运行时地址

重定位算法

// relocation entry
typedef struct {
long offset; // 重定位的偏移
long type:32, // 重定位类型
symbol:32; // 符号表索引
long addend; // 有符号常数,用于偏移调整
};

可执行目标文件

位置无关代码

  • 加载但是不需要重定位代码——位置无关代码(PIC)
  • gcc -fpic,共享库编译需要使用
  • 基于.text和.data的距离总是保持不变

PIC数据引用

  • 在数据段开始创建一个表,全局偏移量表(Global Offset Table)

PIC函数调用

  • 延迟绑定,将过程地址的绑定推迟到第一次调用该过程时
  • 通过GOT和PLT(过程链接表)来实现;PLT是代码段的表,GOT是数据段的表
  • 通过两个表的跳转,将函数的ID和动态链接器的参数压入栈中,进入动态链接器进行重定位和修复符号执行的地址
    • 第一条PLT指令通过GOT[4]进行间接跳转;跳转只是跳到下一条指令

库打桩机制

  • 运行截获对共享库函数的调用,用自己的函数进行取代