链接和加载的补充

链接和加载的补充

2024 南京大学《操作系统:设计与实现》
链接和加载的补充

动态加载、GOT 和 PLT 🌶️

两个大问题

void foo(); ... foo();
extern int x; ... x = 1;
  • foo 和 x 的位置都可能在加载时确定
    • 因此需要一个 GOT[·]
    • foo: 二级跳转
      • call foo@plt → call *GOT[foo] (动态链接库)
      • call foo (同一链接单元)
    • x (stderr): 比想象中麻烦
      • -fPIE: *x(%rip) = 1; -fPIC: **x(%rip)
      • 依然可以访问共享库中的 x (这是如何做到的 😂)
2024 南京大学《操作系统:设计与实现》
链接和加载的补充

动态链接相关的命令行工具

可执行文件仍然是 “状态机初始状态”

  • 我们应该有工具可以查看它
  • ldd - Print shared object dependencies
    • SEE ALSO 一直是手册里的宝藏:ld.so (8)

学习方法与建议

  • ATFAI: 从此单纯的 “知识” 不再是壁垒和禁区
    • 对于一个动态链接的二进制文件,execve 后的第一条指令在哪里?
    • 如何编译出一个不使用默认 ld.so 作为 interpreter 的 ELF 动态链接可执行文件?
2024 南京大学《操作系统:设计与实现》
链接和加载的补充

动态加载器的实现

满足可执行文件提出的 “要求”

  1. 把所有直接/间接依赖的库都映射到内存 (.dynamic)
  2. 填入 GOT 表项 (.rela.dyn, .rela.plt)
    • PLT 可以延迟绑定 (lazy binding)
    • 但似乎现在也不延迟绑定了

加载器也提供了 “随时可用” 的版本

void *dlopen(const char *filename, int flags);
void *dlsym(void *handle, const char *symbol);
2024 南京大学《操作系统:设计与实现》
链接和加载的补充

LD_PRELOAD: 让我们打一点小主意

如果能链接我们 “修改” 过的 libc 就好了

  • 比游戏修改器更优雅的 “入侵” 地址空间方法
  • 程序会主动把控制流交给我们

LD_PRELOAD: 在加载之前 preload

  • 甚至我们都不需要修改 libc
    • 动态加载的全局符号:先到先得
      • AI 上课时间:如何使用 LD_PRELOAD 替换 malloc 为我的实现?
      • 如何使用 Windows API 实现 DLL 注入 trace?
        • Open Question: 如何反游戏外挂?
2024 南京大学《操作系统:设计与实现》