《Windows核心编程系列》谈谈基址重定位和模块绑定

发表于:2012-9-06 09:54

字体: | 上一篇 | 下一篇 | 我要投稿

 作者:ithzhang    来源:51Testing软件测试网采编

  每个DLL和可执行文件都有一个首选基地址。它表示该模块被映射到进程地址空间时最佳的内存地址。在构建可执行文件时,默认情况下链接器会将它的首选基地址设为0x400000。对于DLL来说,链接器会将它的首选基地址设为0x10000000,然后将该地址以及代码、数据的相关地址都写入它们的PE文件中。当它们被加载时,加载程序读取首选基地址的值,并试图把它们加载到相应位置。

  对于可执行文件和DLL中的代码,它们运行的时候所引用的的数据的地址,在链接的时候就已经确定。并且这些都是当exe文件或是DLL被加载到它们的首选基地址处时才是有效的。

  对于汇编代码:MOV [0x00414540] ,5

  它是将5赋值给0x00414540处的内存地址。此地址已经固定。它说明当EXE或是DLL被加载到0x400000处时,0x00414540才是正确的。然而并不是所有模块都会被载入到首选基地址处。一旦模块没有被加载到首选基地址处,在该模块中对于地址的引用都是错误的,这时候基址重定位就是必须的。

  所谓重定位就是当某模块未被载入到首选基地址时,加载器会计算模块实际载入的地址跟首选基地址的差值,将这个差值加到机器指令所引用的原来的地址,得到的就是模块中各指令所引用的数据在本进程地址空间的正确地址,随后加载器会修正模块中对每个内存地址的引用。

  为了便于系统有能力对各数据的地址进行修正,windows提供了重定位段。它包含很多基址重定位信息。这个段是有很多项组成。每一项表示一个要重定位的地址,它包含一个字节偏移量列。该偏移量表示一条机器指令所使用的内存地址。这便于系统在确认该模块需要重定位时对需要重定位的数据进行定位。

  当链接器在构建模块时,它会将重定位段嵌入到生成的文件中。

  对exe文件来说,由于每个文件总是使用独立的地址空间,所以exe文件总是可以被加载到首选基地址上。对于DLL来说,很多DLL都是使用寄主进程的地址空间,不能保证各DLL的首选基地址各不相同。

  所以DLL一定要有重定位段,除非在链接时使用/FIXED 开关。此时链接器会去掉重定位段。如果此后模块未被载入首选基地址,由于无法重定位,模块不会被载入,导致程序无法运行。

  如果加载程序将模块加载到它的首选基地址,那么系统就不会访问模块的重定位段。否则系统会打开模块的重定位段并遍历其中的条目,对每个条目,加载程序先找到包含机器指令的那个存储页面,算出差值,将差值加到机器指令当前正在使用的内存地址上。

  对于上例:假如它是在一DLL中。如果该DLL实际被加载到0x20000000处,由于首选基地址是0x10000000,两者差为0x10000000。加载器修正之后,该指令所引用的实际地址变成了0x10414540。这样对各个数据的引用都会引用到正确的地址 。

  要知道基址重定位需要很大的系统开销:

  1:加载程序需要遍历模块重定位段并修改模块中大量的代码。这增加了程序初始化时间。

  2:当加载程序写入模块的代码页面时,由于它们具有写时复制属性,写时复制机制会导致系统从页交换文件中分配空间来容纳这些修改后的页面。

  明白了这些我们应该清楚,为每个映射到进程的DLL设置不同的首选基地址是必须的。在链接时,选中ProjectProperties\Linker\Advancved,然后在BaseAddress中设置。这听起来很容易,但是如果程序需要载入大量的模块,我们还需要这样一个一个设置吗?话又说回来了,有些模块并不是我们创建的,我们应该怎么办呢?

  Windows为我们提供了一个名为:Rebase.exe的工具。

  如果在执行它时为它提供一组映像文件名,它会执行以下操作:

  1:它会模拟创建一个地址空间。

  2:它会打开这一组映像文件,并得到它们的大小和首选基地址。

  3:它会在模拟的地址空间对模块重定位的过程进行模拟,以便各模块没有交叉。

21/212>
《2023软件测试行业现状调查报告》独家发布~

关注51Testing

联系我们

快捷面板 站点地图 联系我们 广告服务 关于我们 站长统计 发展历程

法律顾问:上海兰迪律师事务所 项棋律师
版权所有 上海博为峰软件技术股份有限公司 Copyright©51testing.com 2003-2024
投诉及意见反馈:webmaster@51testing.com; 业务联系:service@51testing.com 021-64471599-8017

沪ICP备05003035号

沪公网安备 31010102002173号