您的位置:首页 > 运维架构

关于IMAGE_OPTIONAL_HEADER.SectionAlignment与IMAGE_OPTIONAL_HEADER.FileAlignment 以及内存映射的字节对齐

2012-02-26 15:23 701 查看
关于IMAGE_OPTIONAL_HEADER.SectionAlignment与IMAGE_OPTIONAL_HEADER.FileAlignment 以及内存映射的字节对齐

的关系.

一. PE格式(包括文件中和内存中)是怎么分块对齐的?

PE的大概格式是:

IMAGE_DOS_HEADER +

Stub +

IMAGE_NT_HEADERS +

IMAGE_SECTION_HEADER * n

Section 0

Section 1

...

Section n

分块对齐是这样分的:

------Block 1---------------------

IMAGE_DOS_HEADER +

Stub +

IMAGE_NT_HEADERS +

IMAGE_SECTION_HEADER * n

------Block 2---------------------

Section 0

------Block 3---------------------

Section 1

------Block 4---------------------

...

------Block 5---------------------

Section n

----------------------------------

从Block1 到 Block5都要按指定大小对齐.

其中, PE文件存储在磁盘的对齐是按照IMAGE_OPTIONAL_HEADER.FileAlignment对齐;

PE文件运行的时候再内存中是按照IMAGE_OPTIONAL_HEADER.SectionAlignment对齐.

用VC6生成一个Exe文件, 查看FileAlignment和SectionAlignment, 默认都是0x1000(4k).

一般Block 1比0x1000小的, 所以Block 2的ROF为0x1000.

而运行装载后, Block 2 的RVA一般为0x401000. (PE从0x400000开始装载的).

用VC2008生成一个Exe文件, 查看FileAlignment默认是0x200, SectionAlignment默认都是0x1000.

所以, 假设Block 1大小为0x2E6, 那么, 所以Block 2的ROF为0x400.

而运行装载后, Block 2 的RVA为0x401000. (PE从0x400000开始装载的).

而我们用CreateFileMapping打开一个文件时, 也是把文件加载到内存, 这个也是要对齐的,

但是这种对齐是针对整个文件的(这个也是基于0x1000对齐的).

区别是CreateFileMapping的对齐是针对这个文件的, 而PE文件运行装载的内存对齐是针对块的, 例如上面说的Block 1 ---- Block 5,

http://bbs.pediy.com/archive/index.php?t-90067.html

/ALIGN指定节的内存对齐属性,要更改节的文件对齐,

可以指定一个未公开的链接器选项"/FILEALIGN:#"来指定,例如"/FILEALIGN:0x1000"

#pragma comment(linker, "/ALIGN:0x1000")

#pragma comment(linker, "/FILEALIGN:0x1000")  // 验证了, 写在代码里没效

在 VC2008 中这样写就说第2行是无效指令,只能在项目属性的|连接器|命令行|附加选项里写.

我用VC2008修改如下

(FileAlignment默认是0x200, SectionAlignment默认是0x1000)

1.

SectionAlignment(/ALIGN:0x1000)

FileAlignment(/FILEALIGN:0x1000)

可以运行(其实这个配置就VC6的默认配置)

2.

SectionAlignment(/ALIGN:0x200)

FileAlignment(/FILEALIGN:0x1000)

报不是Win32应用程序.

3.

/ALIGN指定节的内存对齐属性,要更改节的文件对齐,就是用/OPT:WIN98,可以指定4k对齐,如果是OPT:NOWIN98,就是512字节对齐.

vs 2008 已经不支持了。

在VC6.0下

FileAlignment和SectionAlignment, 默认都是0x1000(4k).

1.

SectionAlignment(/ALIGN:0x200)

可以运行(只改SectionAlignment, FileAlignment自动变成了0x200)

(有这个警告LINK : warning LNK4108: /ALIGN specified without /DRIVER or /VXD; image may not run)

2.

SectionAlignment(/ALIGN:0x200)

FileAlignment(/FILEALIGN:0x1000)

可以运行(FileAlignment自动变成了0x200)(也就是说再VC6.0中/FILEALIGN:0x1000是无效的)

(有这个警告LINK : warning LNK4108: /ALIGN specified without /DRIVER or /VXD; image may not run)

3.

SectionAlignment(/ALIGN:0x1000)

FileAlignment(/OPT:WIN98)

可以运行(SectionAlignment 0x1000, FileAlignment 0x200)

(有这个警告LINK : warning LNK4108: /ALIGN specified without /DRIVER or /VXD; image may not run)

 

 

 

 

 

 

 

 

 

 

 

 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息