我正在尝试编写一个基本的用户空间ELF加载器,它应该能够加载静态链接(非动态链接)的非可重定位二进制文件(即不用-pie,-fPIE等构建)。它现在应该适用于x86 CPU。
我已经遵循了loading ELF file in C in user space上的代码,并且当可执行文件可重定位时它运行良好,但如果不是因为程序加载到错误的虚拟内存范围并且立即崩溃,则预期完全失败。
但我尝试修改它以在预期的虚拟偏移量下加载程序(使用phdr.p_vaddr)但是我遇到了一个复杂问题:我的加载器已经在使用该虚拟内存范围了!我无法mmap它,更不用说写任何东西了。我如何继续这样我可以将我的不可重定位二进制文件加载到我的加载器的地址空间中,而不会在加载器自己的代码完成之前覆盖它?我是否需要让我的加载程序从完全不同的虚拟内存范围运行,可能是通过让链接器将其链接到通常的虚拟内存范围之上,以获得不可重定位的二进制文件(在我的情况下恰好从0x400000开始)或它有一些技巧吗?
我已经阅读了ELF文档(我在这里使用的是ELF64,但我认为ELF32和ELF64非常相似)和网上的很多文档,我仍然没有得到它。
有人可以解释ELF加载器如何处理这种特殊的复杂情况吗?谢谢!
答案 0 :(得分:2)
Archimedes称为“heureka”。如果您的ELF二进制文件必须位于一个位置,因为您无法将其重建为另一个位置,则必须重新定位加载器本身。
不可重定位的ELF不包含足够的信息来将其移动到不同的地址。您可以编写一个反编译器来检测代码中的所有地址引用,但它不值得。当您尝试分析存储在预初始化变量中的指针等数据引用时,您将遇到问题。
如果您无法获取ELF二进制文件的源代码或可重定位版本,请重写加载程序。
顺便说一句:阿基米德·海瑞卡对于作弊的金匠来说是致命的。我希望你的情况不会那么贵。