DLL 重定位

来源:互联网 发布:linux shell实例 编辑:程序博客网 时间:2024/04/29 06:35

DLL 重定位

在32位代码中,涉及到直接寻址的指令都是需要重定位的(而在DOS的16位代码中,只有涉及到段操作的指令才是需要重定位的,对此有兴趣的读者可以参考 相关的资料),对于操作系统来说,其任务就是在对可执行程序透明的情况下完成重定位操作,在现实中,重定位信息是在编译的时候由编译器生成并被保留     在可执行文件中的,在程序被执行前由操作系统根据重定位信息修正代码,这样在开发程序的时候就不用考虑重定位问题了。 

重定位信息在DLL文件中被存放在重定位表中 
    重定位的算法可以描述为:将直接寻址指令中的双字地址加上模块实际装入地址与模块建议装入地址之差。为了进行这个运算,需要有3个数据,首先是需要修正的机器码地址;其次是模块的建议装入地址;最后是模块的实际装入地址。这就是第一个问题的答案。 

在这3个数据中,模块的建议装入地址已经在PE文件头中定义了,而模块的实际装入地址是Windows装载器确定的,到装载文件的时候自然会知道,所以第二个问题的答案很简单,那就是应该被保存在重定位表中的仅仅是需要修正的代码的地址。 

事实上正是如此,DLL文件的重定位表中保存的就是一大堆需要修正的代码的地址。 
    重定位表一般会被单独存放在一个可丢弃的以“.reloc”命名的节中,但是这并不是必然的,因为重定位表放在其他节中也是合法的,惟一可以肯定的是,如 果重定位表存在的话,它的地址肯定可以在DLL文件头中的数据目录中找到。如表17.4所示,重定位表的位置和大小可以从数据目录中的第6个 IMAGE_DATA_DIRECTORY结构中获取 

    虽然重定位表中的有用数据是那些需要重定位机器码的地址指针,但为了节省空间,DLL文件对存放的方式做了一些优化。 
    在正常的情况下,每个32位的指针占用4个字节,如果有n个重定位项,那么重定位表的总大小是4×n字节大小。 
    直接寻址指令在程序中还是比较多的,在比较靠近的重定位表项中,32位指针的高位地址总是相同的,如果把这些相近表项的高位地址统一表示,那么就可以省略 一部分的空间,当按照一个内存页来分割时,在一个页面中寻址需要的指针位数是12位(一页等于4096字节,等于2的12次方),假如将这12位凑齐16 位放入一个字类型的数据中,并用一个附加的双字来表示页的起始指针,另一个双字来表示本页中重定位项数的话,那么占用的总空间会是4+4+2×n字节大 小,计算一下就可以发现,当某个内存页中的重定位项多于4项的时候,后一种方法的占用空间就会比前面的方法要小。
原创粉丝点击