为什么EXE不能超过4GB
2010-07-13 10:32 lixiong 阅读(10189) 评论(50) 编辑 收藏 举报为什么EXE不能超过4GB
前几天看到大家在讨论EXE装载的问题,很新奇。有的说PE装载受到进程空间的限制,有的说PE一定是整体装入,有的用ZIP自解压包来举例子。
我当时大概想了一下,觉得PE不一定是要整体装入的。PE文件包含一个PE header,里面定义了各个段,比如代码,资源等等的偏移地址,装载的时候应该不会超出这个PE header的定义。也就是说,如果PE header里面定义了最远的段是10M,但是PE文件有100M的话,应该最多只有10M装载。
于是我写了一个程序来测试下。首先写一个简单的C++的helloworld。然后随便在硬盘上找了个700M左右的A片,然后执行下面的命令把这两个文件拼合起来成为一个新的EXE:
copy /B helloworld.exe /B + 常盘みちる.avi /B largepe.exe /B
然后运行这个largepe.exe, 一切正常。在debugger中加载这个largepe.exe后发现,这个module占据的内存空间和helloworld一样,并没有包avi那部分。
所以我在想,既然是这样的话,我可以把很大的数据放到exe文件后面,然后在exe的实现里面来分段读取这些数据,实现自我播放自我解压之类的。为了再次证明这一点,我用dxshow写了一个简单的播放程序,然后用同样的办法拼接了一个4G多的高清版本。运行,发现:
不能运行。说这个是invalid win32 application。
好吧,由此看来,自解压文件不超过4G的确还是有原因的。但是原因到底是什么呢,难道真的和4GB内存空间相关么?于是我换了个64位的机器,运行,发现:
不能运行。说这个是invalid win32 application。
哦,原来64位的机器也不能运行超过4GB的EXE啊,那看来和什么进程内存空间没太大关系了吧。但是原因到底是什么呢,我拿debugger跟到失败前的最后一个API,发现是ZwCreateSection,这个API调用失败并且返回STATUS_INVALID_FILE_FOR_SECTION。额,这里已经超出我的知识范围了,于是就去讨论组问专家,专家Pavel说:
"
SECTION_IMAGE_INFORMATION structure contains a ULONG ImageFileSize field. If we allow files larger than 4 GB, programs that use this structure may break, and that can potentially affect 3rd party apps because all this information is on the web, even though the structure and the APIs using it are not officially documented.
(Note that this is separate from the image size in the PE headers, which is also a ULONG and is currently limited to slightly less than 2 GB.)
--by Pavel
"
原来是这样啊~~~
PS, 附上文SECTION_IMAGE_INFORMATION的结构定义:
http://www.nirsoft.net/kernel_struct/vista/SECTION_IMAGE_INFORMATION.html
typedef struct _SECTION_IMAGE_INFORMATION
{
PVOID TransferAddress;
ULONG ZeroBits;
ULONG MaximumStackSize;
ULONG CommittedStackSize;
ULONG SubSystemType;
union
{
struct
{
WORD SubSystemMinorVersion;
WORD SubSystemMajorVersion;
};
ULONG SubSystemVersion;
};
ULONG GpValue;
WORD ImageCharacteristics;
WORD DllCharacteristics;
WORD Machine;
UCHAR ImageContainsCode;
UCHAR ImageFlags;
ULONG ComPlusNativeReady: 1;
ULONG ComPlusILOnly: 1;
ULONG ImageDynamicallyRelocated: 1;
ULONG Reserved: 5;
ULONG LoaderFlags;
ULONG ImageFileSize;
ULONG CheckSum;
} SECTION_IMAGE_INFORMATION, *PSECTION_IMAGE_INFORMATION;