我一直在寻找到窗口的PE格式最近,我注意到,在大多数例子中,人们往往会设定ImageBase
的偏移值optional header
的东西不合理的高像0x400000
。
什么可以使它不利不映射在偏移图像0x0
?
我一直在寻找到窗口的PE格式最近,我注意到,在大多数例子中,人们往往会设定ImageBase
的偏移值optional header
的东西不合理的高像0x400000
。
什么可以使它不利不映射在偏移图像0x0
?
首先,这不是Windows或PE文件格式的默认,它是为连接器的/ BASE选项的默认,当你用它来连接一个EXE。 一个DLL默认为0x10000000的。
选择/ BASE:0将是不错的选择,任何程序都在该基地的地址永远运行。 第一个64 KB的地址空间被保留,并且永远不会被映射。 主要抓空指针引用错误。 并扩大到64KB赶上程序指针错误,在16位开始的生活,结果被编译到32位。
为什么0x40000,而不是0x10000的是默认的是历史的偶然,以及和可以追溯到至少是Windows 95哪家保留第4兆字节为“16位/ MS-DOS兼容竞技场”的地址空间。 我不记得了吧,Windows 9x中有从NT一个非常不同的16位虚拟机的实现。 你可以阅读一些更多关于它的这个古老的知识库文章 。 这当然是不相关了,这些天,一个64位操作系统将很容易在0x010000和为0x400000之间的空间分配堆内存。
没有改变的一个EXE的/ BASE选项的任何一点。 然而,有很多点的改变它的DLL。 他们是更有效的,如果他们不重叠,因此不必搬迁,他们不会采取在分页文件中的任何空间,并可以在进程间共享。 甚至还有它的SDK工具,这样你就可以建成后改变它,rebase.exe
实际上,设置/ BASE为0的影响取决于地址空间布局随机化(ASLR)图像的设置(也被连接器放在- / DYNAMICBASE:NO )。
如果您的图像有/ BASE:0和ASLR是(/ DYNAMICBASE:YES),那么你的形象将启动并运行,因为加载器将自动以一个“有效”的地址加载它。
如果您的图像有/ BASE:0和ASLR关闭(/ DYNAMICBASE:否),那么你的图像将不会启动,因为加载程序将不期望的基于地址加载它(这是,如上面所解释的,unvalid /保留)。
如果你映射它然后地址0,则意味着该代码希望运行起始地址为零。
对于OS,零地址是NULL
,这是一个无效的地址。
(不是“根本”,但对于现代的操作系统,它是。)
另外,一般你不想在内存的低16 MIB(甚至虚拟的)东西,出于多种原因。
但是,什么是另类? 它在某处被映射,所以他们选择了0x400000
......没有特别的原因在于特定的地址,大概。 这可能只是方便。
微软选择了地址通过该PE文件将被内存映射链接指定的默认起始地址。 链接器假定这个地址,并且可以优化与假设的可执行文件。 当文件被存储器映射在该地址的代码可以在不需要修改任何内部偏移来运行。
如果由于某种原因该文件不能被加载到该位置(另一个EXE / DLL已经加载在那里)迁移需要将之前的可执行程序可以运行,这将增加加载时间发生。
更低的内存地址通常认为含有低级别的系统程序和一般单独留在家中。 对于基址地址唯一真正的要求是,它是0x10000的倍数。
推荐阅读: