VC生成的可执行二进制模块是PE格式的,前面我们讲过,文件的开始处是一个PE文件头,而这个头的长度是可变的。同时在这个头中的特定偏移处(即IMAGE_OPTIONAL_HEADER中的AddressOfEntryPoint)指定了这个模块的入口地址。Windows加载器在加载这些模块的时候,根据PE头来找到入口地址,然后跳转到入口地址去执行。
而在我们的OS开发中,如果再进行这样的处理,可能就比较麻烦,有的情况下甚至是不可能的。我们OS开发的要求是直接找到模块的入口地址,通过一条跳转指令跳转到该地址开始执行。
为了解决这个问题,可以通过对目标文件进行修改的方式来解决。process工具就是完成这项工作的。这个工具软件读入目标文件的头,找出目标文件的入口所在位置,然后在文件的开始处加上一条跳转指令,跳转到入口处即可。这样处理之后,在我们OS核心模块的加载过程中,只要把这个模块读入内存,并直接跳转到开始处执行即可。
但是这样做的前提是,PE文件在磁盘上的布局,与其被加载到内存后的布局保持一致。即前面介绍的两个概念—虚拟相对地址和文件相对地址,是一样的。在Visual C++6.0中,可通过设定/Alignment和/Base等几个选项,来确保这个条件能够满足。同时通过设置/Entry编译选项,使得入口点指向一个特定的入口函数(比如__init函数)。根据作者的经验,这在VC 6.0下是可以正常工作的,但是到了VS 2003以上的编译环境,就出现了问题,通过设置这些选项不能解决内存布局和文件布局一致的问题。具体解决方案,在14.3.2节中再进行介绍。(www.xing528.com)
process工具的工作原理非常简单,就是读取PE文件,从PE头中找到AddressOfEntry Point,然后把AddressOfEntryPoint的值填写到PE头中。这样处理的结果是,PE头会被破坏,至少MS-DOS头已经被破坏。但这不要紧,Hello China不关注MS-DOS头。
具体代码比较简单,我们就不看了。这个工具的使用方式如下:
工具把src_filename指定的文件读入内存,修改其文件头部,然后把修改后的文件重新写入到dst_filename文件中。这样源文件的内容不会受到影响。
免责声明:以上内容源自网络,版权归原作者所有,如有侵犯您的原创版权请告知,我们将尽快删除相关内容。