我正在构建一个自定义 ELF 对象加载器,它解析库依赖项(DT_NEEDED)并递归加载这些依赖项,执行重定位和符号解析,调用 preinit 等。ld.so 被忽略(DT_INTERP),并且我的加载器尝试执行以下操作ld.so 通常会这样做,不是因为我认为这是明智的做法,而是因为我试图充分理解该过程的细节,以调试我在 JIT 编译器中遇到的似乎涉及 PLT 的问题我还不太了解的问题。也许出于自虐,我决定从头开始实现动态加载器和链接器来学习这些细节(并检查我是否真正理解它们)。
作为该过程的一部分,我尝试与 GDB 集成,以便它了解我正在加载的新 ELF 对象(无 dlopen())。使用 GDB 的 JIT 接口 可以轻松完成此任务,现在 GDB 可以看到我加载的 ELF 对象中的符号,但地址错误(地址是正确的,但尚未重新定位以匹配所选的基地址)通过
mmap
给定 addr=NULL)。我没有看到任何与调试信息相对应的 DT_RELA
/ DT_REL
/ DT_JMPREL
条目。是否需要执行一些单独的步骤来重新定位 ELF 中的调试信息?
调试信息由
gcc
使用 -g
和 -gdwarf-5
构建(两者显示相同的结果:调试符号报告其在 gdb 中未重定位的值)。
如果相关的话,我正在使用Linux(Ubuntu),x86_64,不链接到libc:
-fPIC -gdwarf-5 -nostartfiles -nodefaultlibs
。
我花了一些时间尝试用谷歌搜索这个问题,但明智的程序员不会这样做,所以结果很少。我确实看到了 dwarf-5 以某种方式使用位置无关符号的建议,但我看到的结果似乎并没有反映出这一点。