可执行文件中的数据位于奇怪的位置

时间:2013-03-10 16:33:56

标签: c assembly linker exe portable-executable

几天前我开始玩PE格式了。我做过小型PE加载器,可以根据虚拟地址将段加载到内存中。例如,我在虚拟地址.text上有0x1000部分,在.data上有部分0x2000。使用我的小汇编代码,我在一些空闲位置(0x10000)加载了PE文件,并从它的位置加载了PE部分。因此,.text部分位于0x110000x10000 + 0x1000),.data位于0x12000等...但是当我从{{{{}}引用我的数据时1}}位置,我发现(在反汇编中)它指向.code。在互联网上我找到了像图像库这样的特定于每种类型的图像...但我不明白当在Windows中运行大量可执行文件时如何将0x402000加载到.exe例。有人为什么这样,它是如何工作的,我怎样才能在我的基本系统中实现它?

请帮忙。

3 个答案:

答案 0 :(得分:3)

虚拟内存意味着计算机上的每个进程都可以使用“相同”的地址,因为每个进程的地址空间是独立的。对于进程B,进程A的0x400000映射到不同的物理地址而不是0x400000,即使它们是相同的虚拟地址(不同的虚拟地址空间)。 / p>

可执行文件的默认基址是0x400000。您的链接器将该基址硬编码到可执行文件中,并将适当地调整地址引用。程序启动时,您的可执行文件将加载到该地址。您的汇编器或链接器应该为您提供一种更改此默认基址的方法。

请注意,另一方面,DLL必须加载到唯一的地址,因为它们必须在同一进程中共存。出于这个原因,DLL通常是可重定位的,即它们在加载时可以具有任何基地址,以应对将它们放在唯一地址的要求。 (在系统上有多个不可重定位的DLL可能会导致问题,但在系统上有多个不可重定位的.exes根本就没问题。)

答案 1 :(得分:3)

每个可执行文件都在自己的virtual address space中运行。因此,即使两个可执行文件具有相同的0x400000图像库,它们也会驻留/使用不同的物理内存。可以把它想象成图像库的基础不同。

要获取加载到正在运行的流程中的模块的图像库,您可以使用GetModuleHandle。它返回模块的句柄,该句柄非常等于图像库。或者,您可以从PE标头IMAGE_OPTIONAL_HEADER结构(see here)中的ImageBase字段获取图像库。

答案 2 :(得分:1)

这是一个复杂的主题,但由于虚拟内存和硬件辅助的进程分离,每个进程都会加载,并给人一种印象,即它拥有整个地址空间。因此,所有图像库都可以从相同的地址开始,因为虚拟内存中的地址可以映射到内存的任何位置,并且就所涉及的情况而言,该进程具有无限的内存。