实现库的运行时加载

若干要素

  • 编译成位置无关代码
    • lea (0x400000), addr_of_x (no)
    • lea 12(%rip), addr_of_x (yes)
    • 这是编译器可以实现的
  • 对外部库函数的调用是查表的
    • call TABLE(x)
  • 在运行 (加载) 时填表
    • 加载时把导出的符号填入 TABLE

我们 “发明” 了 GOT (Global Offset Table)

  • 就是 TABLE

一个有趣的问题

extern void foo();

编译器遇到函数调用,应该翻译成哪种指令?

  • 如果 foo 来自同一个动态链接库
    • call foo
  • 如果 foo 来自另一个动态链接库
    • call TABLE(foo)

我们发明了 PLT (Procedure Linkage Table)

  • 函数实在太多了
    • 每个都标记区分,太难看了
  • 编译器总是生成一个直接的 call
    • 来自另一个动态链接库:call putcahr@PLT