Spiga

为什么EXE不能超过4GB

2010-07-13 10:32 by lixiong, 5725 visits, 收藏, 编辑

为什么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;

Add your comment

48 条回复

  1. #1楼 Galactica      2010-07-13 10:37
    把ULONG换成_int64,把WORD换成DWORD
     回复 引用 查看   
  2. #2楼 dongzz      2010-07-13 11:07
    然后随便在硬盘上找了个700M左右的A片。。。
     回复 引用 查看   
  3. #3楼 YJJ      2010-07-13 11:12
    然后随便在硬盘上找了个700M左右的A片............
    跪求链接:<
     回复 引用 查看   
  4. #4楼 Neoo      2010-07-13 11:13
    楼主,求种子~ hotneo2002@163.com
     回复 引用 查看   
  5. #5楼 young40      2010-07-13 11:28
    然后随便在硬盘上找了个700M左右的A片............
     回复 引用 查看   
  6. #6楼 dotNetDR_      2010-07-13 11:30
    在这个和谐网络中,楼猪居然"随便"就能搞到700M的阿片.厉害~~~~!

    另{2,3,4,5}楼汗一个!
     回复 引用 查看   
  7. #7楼 深山老林      2010-07-13 11:35
    楼主说的是光盘的A面。
     回复 引用 查看   
  8. #8楼 mikelij      2010-07-13 11:35
    我也是刚刚同园友讨论才知道的. PE header当中的SizeOfImage可以决定装载进内存的大小. 象zip, rar的自解压程序都是如此.
     回复 引用 查看   
  9. #9楼 xiaotie      2010-07-13 12:01
    求700M
     回复 引用 查看   
  10. #10楼 咕嚕咕嚕      2010-07-13 12:23
    无图又无种 菊花万人捅!
    ps:求700M
     回复 引用 查看   
  11. #11楼 iTech      2010-07-13 12:30
    你在64bit上运行说invalid win32 application,是因为你的程序还是32bit的吧,所以进程最大只能4G内存
     回复 引用 查看   
  12. #12楼 iTech      2010-07-13 12:31
    再河蟹,那个东西还是容易找的吧,一找一堆啊!
     回复 引用 查看   
  13. #13楼 Milo Yip      2010-07-13 12:32
    似乎不少園友都希望取得測試用的數據,真嚴謹
     回复 引用 查看   
  14. #14楼 iTech      2010-07-13 12:34
    怎么没有总结:

    exe真的不能超过4G?

    我确定的是:exe运行的某一时刻所分配的内存不能超过4G!
     回复 引用 查看   
  15. #15楼 Tony Qu      2010-07-13 13:26
    这帖子要顶!
     回复 引用 查看   
  16. #16楼 Domslab      2010-07-13 13:26
    引用然后用同样的办法拼接了一个4G多的高清版本


    为了验证博主的实验,跪求这个4G文件
     回复 引用 查看   
  17. #17楼 grapeot      2010-07-13 13:35
    为了验证博主的实验,跪求这个4G文件
     回复 引用 查看   
  18. #18楼 +-+      2010-07-13 13:39
    32位CPU地址空间最大4G,当新建进程CR3确定后,建立进程地址空间分配,当然最多只能建立4G内存map对象—>Section(指可最大映射的虚拟内存地址空间)。
     回复 引用 查看   
  19. #19楼 assiwe      2010-07-13 13:42
    鄙视上面要A片的.

    求largepe.exe以作测试
     回复 引用 查看   
  20. #20楼 Q      2010-07-13 14:35
    700M A片是本文亮点
     回复 引用 查看   
  21. #21楼 黄明      2010-07-13 15:07
    公司不方便 晚上发地址
     回复 引用 查看   
  22. #22楼 youqianer      2010-07-13 15:11
    现在这么大的片不好找呀。。。
     回复 引用 查看   
  23. #23楼 阿瑞|www.16hi.com      2010-07-13 16:09
    32位的 应该只有3G左右可以使用吧
     回复 引用 查看   
  24. #24楼 Arthas-Cui      2010-07-13 16:30
    为了验证lz的第一步,
    求700M左右的A片的种子。
     回复 引用 查看   
  25. #25楼 诺贝尔      2010-07-13 16:31
    如果对英文做翻译,那样就更好了。毕竟不是人人都懂英文。
     回复 引用 查看   
  26. #26楼 Response.Write("zjz")      2010-07-13 16:39
    我看明白了,是常盘贵子吧
     回复 引用 查看   
  27. #27楼 Fisher WEI      2010-07-13 16:49
    你在64bit尝试的时候,是用x64的编译环境重新搞的么?
     回复 引用 查看   
  28. #28楼 小刚qq      2010-07-13 17:31
    博主应该感到悲哀..

    有一半回复的都是冲着A片来的...

    我也感叹下这个社会...
     回复 引用 查看   
  29. #29楼 慕少艾      2010-07-13 17:57
    大家都是 冲着 700mb 来的
     回复 引用 查看   
  30. #30楼 airwolf2026      2010-07-13 18:33
    @Milo Yip
    大大的回复,哇哈哈,笑抽啦.
     回复 引用 查看   
  31. #31楼 iTech      2010-07-13 18:38
    楼主的娱乐精神可嘉!顶!
     回复 引用 查看   
  32. #32楼 lanvv      2010-07-13 20:34
    A片 博主指的是美国片 American movie 大家理解错了 = =
     回复 引用 查看   
  33. #33楼 Motto(Momo)      2010-07-13 23:46

    引用lanvv:A片 博主指的是美国片 American movie 大家理解错了 = =


    这个大家都知道的,是吧?!
     回复 引用 查看   
  34. #34楼 梦 境      2010-07-14 01:06
    A片很容易得到啊

    我电脑上有9.68 GB (10,398,974,776 字节)
     回复 引用 查看   
  35. #35楼 Ivony...      2010-07-14 01:45
    1、用copy连接起来的文件,PE头还是原来的(换言之不管文件多大,你的PE Header的ImageFileSize还是原来的文件的大小)。

    2、一个32位的程序并不会因为在x64的操作系统上跑就会自动变成x64的,地址空间还是4G不会变。
     回复 引用 查看   
  36. #36楼 东华一只球      2010-07-14 08:44
    非常少见,那么多的xd对测试数据如此感兴趣~~~
     回复 引用 查看   
  37. #37楼 徐少侠      2010-07-14 09:25
    文章是技术贴
    回帖都搞成娱乐贴

    不过活跃下气氛也好

    小心潜水的MM程序员哦。楼上要测试数据的都小心了。
     回复 引用 查看   
  38. #38楼 snow365      2010-07-14 09:49
    700mb的电影一定是DVDRip吧?
     回复 引用 查看   
  39. #39楼 nzperfect      2010-07-14 09:56
    这样子啊
     回复 引用 查看   
  40. #40楼 感恩的心      2010-07-14 11:59
    700m?
    怎么这么多人冲这个来的啊?
    奇怪中······
     回复 引用 查看   
  41. #41楼 拒绝浮躁      2010-07-15 00:09
    引用徐少侠:
    文章是技术贴
    回帖都搞成娱乐贴

    不过活跃下气氛也好

    小心潜水的MM程序员哦。楼上要测试数据的都小心了。

    要测试数据的人中也许有MM。。。
     回复 引用 查看   
  42. #42楼 lcs-帅      2010-07-15 01:00
    到google.jp
    搜xiao77
     回复 引用 查看   
  43. #43楼 daodao      2010-07-15 09:26
    贴演示图
     回复 引用 查看   
  44. #44楼 站在天空下的猪      2010-07-15 16:40
    然后随便在硬盘上找了个700个左右的A片............
     回复 引用 查看   
  45. #45楼 MNight      2010-07-19 10:20
    都对那个字母A感兴趣啊
     回复 引用 查看   
  46. #46楼 luotong      2010-07-20 10:59
    @iTech
    楼主文章最下面那段源码的红字标注部分,就是问题的关键。
    是因为数据类型大小的限制。
     回复 引用 查看   
  47. #47楼 DiggingDeeply      2010-12-22 15:25
    Milo看来还是不了解国内的“习俗”啊。
    这个问题能不能从loader找到答案
     回复 引用 查看   
  48. #48楼 banana.totolv      2011-05-05 23:13
    good
     回复 引用 查看