先来看看PE文件框架结构,多看几遍,就不陌生啦
按照进度,今天该学习块表啦。
PE文件到内存的映射。
在执行一个PE文件的时候,Windows并不是在一开始就将整个文件读入内存,而是采用域内存映射文件机制类似的机制。
换而言之,Windows加载器在装载的时候,仅仅是建立好虚拟地址和PE文件之间的映射关系。当且仅当真正执行到某个内存页中的数据时,这个页面才会被从磁盘提交到物理内存,这种机制使文件装入的速度和文件大小没有太大的关系。但是需要注意的是,系统装载可执行文件的方法又不完全等同于内存映射文件。当使用内存映射文件的时候,系统对“原著”相当忠实,如果将磁盘 文件和内存映像相比较的话,可以发现,不管是数据本身还是数据之间的相对位置,都是完全相同的。在装载可执行文件的时候,有些数据在装入前会内预处理,如重定位,正因如此,载入以后, 数据之间的相对位置可能发生微妙的变化。所以下面图中,内存与物理实存并不是完全对应,中间出现了空白区域:
Windows装载器在装载DOS部分,PE文件头部分和去块表部分是不进行任何特殊的处理的,而装载去块的时候,则会自动按节的属性作不同的处理。如下图:
至于装载器做什么处理,如下:
◆ 内存页的属性
◆ 块的偏移地址
◆ 块的尺寸
◆ 不进行映射的节
内存页的属性: 对于磁盘来说,所有的页都是按照磁盘映射文件函数指定的属性设置的,但是在装载可执行文件的时候,与块对应的内存页属性要按照块的属性来设置,所以,在同属于一个模块的内存页中,从不同块映射过来的内存页的属性是不同的。
块的偏移地址
块的起始地址在磁盘文件中是按照IMAGE_OPTIONAL_HEADER32结构的 FileAlignment 字段的值进行对齐的,而当被加载道内存中时是按照同一结构中的SectionAlignment字段的值设置对齐的,两者的值可能不同。所以一个块表被装载到内存后相对于文件头的偏移地址和磁盘中的偏移地址可能是不同的。(块表事实上就是相同属性数据的组合,当块表再入到内存中的时候,相同一个快比爱所对应的内存页都将被赋予相同的页属性,事实上Windows 系统对内存属性的设置是以页为单位的进行的,块表在内存的对齐的单位必须是一个页的大小或者是一个页的正整数倍)。在磁盘中没有这个限制,因为磁盘中排放的是以空间为主导,在磁盘知识存放,不是使用,所以不用设置那么详细的属性。
块表的尺寸
主要有2个方面:
1,磁盘映像和内存映像中块表对齐存储单位的不同而导致了长度不同
2,对于包含为初始化数据的块表处理问题,既然是没有初始化,那么没有必要为其在磁盘中浪费空间资源,但是在内存中不同,程序一旦运行,之前没有初始化的数据便有可能要被赋值初始化,那么就必须为他们留下空间。
不进行映射的块表
有些块表并不需要映射到内存中,例如 .reloc 块表,重定位数据对于文件的执行代码是透明的,它只是提供Windows装载器使用执行代码根本不会去访问他们,所以没有必要将他们映射到物理内存中。