【问题标题】:load-time ELF relocation加载时 ELF 重定位
【发布时间】:2010-11-23 20:42:00
【问题描述】:

我正在 Linux 下编写一个简单的用户空间 ELF 加载程序(为什么?为了“好玩”)。目前我的加载器非常简单,旨在仅加载包含与位置无关的代码的静态链接 ELF 文件。

通常,当一个程序被内核的 ELF 加载器加载时,它会被加载到它自己的地址空间中。因此,数据段和代码段可以加载到 ELF 段中指定的正确虚拟地址。

然而,就我而言,我通过mmap 向内核请求地址,并且可能会或可能不会获得ELF 段中请求的地址。这对于代码段来说不是问题,因为它与位置无关。但是,如果数据段没有加载到预期的地址,代码将无法正确引用存储在数据段中的任何内容。

确实,我的加载器似乎可以与不包含任何数据的简单程序集可执行文件一起正常工作。但是只要我添加一个数据段并引用它,可执行文件就无法正确运行或 SEGFAULTs。

如果可能的话,我如何修复对数据段的任何引用以指向正确的位置?为此目的,(静态)ELF 文件中是否存储了重定位部分?

【问题讨论】:

  • 在提供请求的地址时 mmap() 失败的原因是因为调用 mmap 的进程已经在其地址空间中分配了这些页面吗?
  • 是的,大概就是这个原因。我曾想过让ld 将我的代码/数据放在“不碍事”的某个地方,但我想知道是否可以首先使用通用解决方案。如果我在这里没有得到任何回复,我可能会继续尝试。

标签: c linux loader elf


【解决方案1】:

如果您修改 .got 部分中可用的绝对地址,(全局偏移量表)您的程序应该可以工作。确保修改绝对地址计算以适应 .text 和 .data 之间的新距离,恐怕您需要弄清楚这些信息来自哪里,适合您的架构。

看到这个:Global Offset Table (Processor-Specific)

祝你好运。

【讨论】:

  • 不应尝试计算新的距离。一些指令可能会使用相对寻址来引用数据段的内容,将段移开只会破坏它。要正确映射段,应使用MAP_FIXED,因此如果所需区域不可用,mmap 调用将失败,和/或自动映射两个段的大区域,然后取消映射其中的部分并将各个段映射到位孔。
【解决方案2】:

我看不出有任何方法可以做到这一点,除非您完全模拟内核提供的虚拟地址空间,并在该虚拟空间内运行代码。当您从文件中映射数据部分时,本质上是将其重新定位到 ELF 解释器的虚拟地址空间的未知地址,并且您的代码将无法以任何方式引用它。

很高兴被证明是错误的。在这里可以学到一些很酷的东西。

【讨论】:

  • 或者在不同的进程中拥有目标 ELF 和加载器功能,其中最少的部分需要在目标进程中的一个怪异地址上。这样您就可以对大多数加载程序使用标准工具和程序
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-10-25
  • 2011-01-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-12-30
  • 2013-06-20
相关资源
最近更新 更多