那么大多数二进制文件都是由reloc表组成的?

时间:2011-05-14 14:12:13

标签: portable-executable relocation

我刚用objdump -x ...检查PE文件的各个部分。

大约有90,000行reloc条目:

reloc   92 offset  bc0 [524bc0] HIGHLOW
reloc   93 offset  bc4 [524bc4] HIGHLOW
    ....

大多数PE文件的大部分空间是否都由上面的reloc条目组成?

这些条目是什么?

更新

任何人都可以解释重定位条目的工作方式如上所述?

1 个答案:

答案 0 :(得分:10)

当内存中存在基本冲突时,需要重定位。如果动态链接库想要在某个内存空间中加载其代码段,但是当它已被另一个模块控制时,它必须加载到不同的位置。但是,通过将其加载到不同的地址空间,它会混淆库所引用的所有绝对引用。例如,假设可执行文件有一个名为int dummy;的全局变量,该变量位于0x602315中。每当访问/写入此变量时,程序执行以下操作码(假设代码位于0x524BBE,与您提到的条目相同):

0x524BBE: MOV EAX, DWORD PTR DS:[0x602315];//move dummy to eax register to do stuff

当库被加载到不同的空间时,0x602315将不会指向该变量,因为其他模块已经占用了地址空间0x602315。因此,要解决此问题,您必须告诉PE加载程序将位移(|new base address-expected base address|)添加/减去此值(0x602315)。为此,每个PE都包含一个名为重定位表的表,该表包含代码中引用此变量的所有偏移量。

所以,假设代替0x524000(预期的基本偏移量),库被加载到0x700000。然后,PE加载器将执行的操作是查找表中的条目并将位移(0x700000-0x524000 = 0x1DC000)添加到偏移量(0x602315),以便加载的代码如下所示:

0x700BBE: MOV EAX, DWORD PTR DS:[0x7DE315];//move dummy to eax register to do stuff

将运行正常,因为它指向变量dummy的正确位置。

回到你的问题,objdump的输出显示了这个表的每个条目。 92可能表示条目的索引,BC0是访问变量的代码的相对地址,[524BC0]将是相对地址+预期基本偏移的结果。和HIGHLOW只是一种重定位(这基本上保留供将来使用。目前,只有一种类型的重定位(HIGHLOW)被使用,所以你不必担心其他类型)。当加载程序读取此条目时,它将更改0x524BC0的值以反映此更改。

关于由.reloc表组成的关于PE的多数空间的问题,答案是它取决于。如果你的程序经常访问全局变量和常量,它将有一个巨大的重定位表,因为加载器必须更新这么多的地方。