It seems to me it's always going to be 4GB, because it uses the same size datatype (A DWORD)? Isn't a DWORD for the SizeOfImage
always going to be 32-bits? Or am I mistaken about this limitation?
4GB does indeed to seem to be the hard limit of ALL Portable Executable's (32-bit and 64-bit PE+).
According to the spec it is 32-bit unsigned value for a PE32+ image just like a PE32 image.
However, in my testing with both 32-bit and 64-bit applications (PE32/PE32+ files) on Windows 7 SP1 Home Premium x64, the maximum file size for either is between 1.8-1.85GB.
I tested by creating a very basic C executable with Visual Studio (~8K for 32-bit and 9K for 64-bit) and the added an empty code section to the PE header until Windows would no longer load it, and then binary searched for the limit. Looking at the process with vmmap showed that almost all of the entire first 2GB of address space were the image (including any subsequently loaded DLLs such as kernel32.dll). The limit was the same for me with both 32 and 64-bit processes. The 64-bit process did have the flag set in it's NT Header's File Header's section stating that it could handle addresses >2GB. It also could allocate memory for non-image sections above the 2GB limit.
It seems like the image is required to fit in it's entirety in the lower 2GB of VA space for the process, which means the SizeOfImage is being treated a signed 32-bit integer by the loader effectively.
The ImageSize field in the PE headers is largely unrelated to the file size on-disk of the PE file. ImageSize is the in-memory size of the loaded image i.e. the size of all sections (each rounded to the SectionAlignment boundary) + size of the PE headers (given in the next header field, SizeOfHeaders). This value cannot be > 2GB for either PE32 or PE32+ because a) the spec says so and b) there exist 31-bit RVAs in the spec, e.g. in the import lookup table. RVAs are memory references given as offsets from the in-memory base address.
That's in memory though. The file on disk can contain data that is not loaded into memory (e.g. debug data, cert data). File pointer fields in the PE spec are 32-bit unsigned values. So the theoretical maximum size of a PE file according to the spec is 4GB.
That's according to the spec. There may be file-system, loader, OS limits outside of the PE spec that reduce the maximum further.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With