在用户空间加载不可重定位的静态 ELF 二进制文件
Loading a non-relocatable, static ELF binary in userspace
我正在尝试编写一个基本的用户space ELF 加载程序,它应该能够静态加载 linked(而不是动态 linked)不可重定位的二进制文件(即不是用 -pie、-fPIE 等构建的)。它现在应该可以在 x86 CPU 上工作。
我已经按照 loading ELF file in C in user space 上的代码进行操作,当可执行文件可重定位时它运行良好,但如果不是可执行文件则完全失败,因为程序加载到错误的虚拟内存中 运行ge 并立即崩溃。
但我尝试修改它以将程序加载到它期望的虚拟偏移量(使用 phdr.p_vaddr)但是我 运行 陷入了一个复杂的问题:我的加载程序已经在使用该虚拟内存 运行格!我无法对其进行映射,更不用说向其中写入任何内容了。我该如何继续,以便我可以将不可重定位的二进制文件加载到加载程序的地址 space 中,而不会在完成之前覆盖加载程序自己的代码?我是否需要从一个完全不同的虚拟内存 运行ge 将我的加载器加载到 运行,也许是通过将 linker 加载到 link 它远远高于通常的虚拟内存 运行ge 用于不可重定位的二进制文件(在我的例子中恰好从 0x400000 开始)或者它有什么技巧吗?
我已经阅读了 ELF 文档(顺便说一句,我在这里使用 ELF64,但我认为 ELF32 和 ELF64 非常相似)和网络上的很多文档,但我仍然不明白。
有人可以解释 ELF 加载器如何处理这种特殊的复杂情况吗?谢谢!
Archimedes 调用 "heureka" 时发现在一个位置只能是一个对象。如果您的 ELF 二进制文件必须位于一个位置,因为您无法为另一个位置重建它,则您必须重新定位加载程序本身。
不可重定位的 ELF 包含的信息不足,无法将其移动到其他地址。您可能会编写一个反编译器来检测代码中的所有地址引用,但这是不值得的。当您尝试分析存储在预初始化变量中的指针等数据引用时,您会遇到问题。
如果您无法获得 ELF 二进制文件或可重定位版本的源代码,请重写加载程序。
顺便说一句:Archimedes heureka 对于作弊的金匠来说是致命的。我希望你的情况不会那么贵。
我正在尝试编写一个基本的用户space ELF 加载程序,它应该能够静态加载 linked(而不是动态 linked)不可重定位的二进制文件(即不是用 -pie、-fPIE 等构建的)。它现在应该可以在 x86 CPU 上工作。
我已经按照 loading ELF file in C in user space 上的代码进行操作,当可执行文件可重定位时它运行良好,但如果不是可执行文件则完全失败,因为程序加载到错误的虚拟内存中 运行ge 并立即崩溃。
但我尝试修改它以将程序加载到它期望的虚拟偏移量(使用 phdr.p_vaddr)但是我 运行 陷入了一个复杂的问题:我的加载程序已经在使用该虚拟内存 运行格!我无法对其进行映射,更不用说向其中写入任何内容了。我该如何继续,以便我可以将不可重定位的二进制文件加载到加载程序的地址 space 中,而不会在完成之前覆盖加载程序自己的代码?我是否需要从一个完全不同的虚拟内存 运行ge 将我的加载器加载到 运行,也许是通过将 linker 加载到 link 它远远高于通常的虚拟内存 运行ge 用于不可重定位的二进制文件(在我的例子中恰好从 0x400000 开始)或者它有什么技巧吗?
我已经阅读了 ELF 文档(顺便说一句,我在这里使用 ELF64,但我认为 ELF32 和 ELF64 非常相似)和网络上的很多文档,但我仍然不明白。
有人可以解释 ELF 加载器如何处理这种特殊的复杂情况吗?谢谢!
Archimedes 调用 "heureka" 时发现在一个位置只能是一个对象。如果您的 ELF 二进制文件必须位于一个位置,因为您无法为另一个位置重建它,则您必须重新定位加载程序本身。
不可重定位的 ELF 包含的信息不足,无法将其移动到其他地址。您可能会编写一个反编译器来检测代码中的所有地址引用,但这是不值得的。当您尝试分析存储在预初始化变量中的指针等数据引用时,您会遇到问题。
如果您无法获得 ELF 二进制文件或可重定位版本的源代码,请重写加载程序。
顺便说一句:Archimedes heureka 对于作弊的金匠来说是致命的。我希望你的情况不会那么贵。