Just a quick blog about the different types of managed PE files.
Here's a table:
Description |
C# compiler switch |
PE type |
machine |
corflags |
MSIL |
/platform:anycpu (default) |
PE32 |
x86 |
ILONLY |
MSIL 32 bit preferred |
/platform:anycpu32bitpreferred |
PE32 |
x86 |
ILONLY | 32BITREQUIRED | 32BITPREFERRED |
x86 managed |
/platform:x86 |
PE32 |
x86 |
ILONLY | 32BITREQUIRED |
x86 mixed |
n/a |
PE32 |
x86 |
32BITREQUIRED |
x64 managed |
/platform:x64 |
PE32+ |
x64 |
ILONLY |
x64 mixed |
n/a |
PE32+ |
x64 |
|
ARM managed |
/platform:arm |
PE32 |
ARM |
ILONLY |
ARM mixed |
n/a |
PE32 |
ARM |
|
The MSIL 32 bit preferred and ARM types are new in .NET 4.5. I've left out Itanium, because it's not that interesting.
For legacy reasons pure MSIL files specify x86 as the machine type and when you really want to target just x86 you need to set the (confusingly named) COMIMAGE_FLAGS_32BITREQUIRED flag.
When the COMIMAGE_FLAGS_32BITREQUIRED flag was introduced (back in .NET 1.0) they probably intended it to just mean that the image required a 32 bit architecture (not necessarily x86), but then the C# compiler mapped the /platform:x86 switch to this flag and they were locked into it meaning just x86.
Starting with Visual Studio 2010, the default platform target project setting for executables changed from Any CPU to x86. This was probably because x64 systems were becoming more popular and more people started running into the poor x64 JIT performance and its many bugs.
With the introduction of ARM support in Windows 8 there was now a need for a new flag to avoid the x64 JIT, but still be cross platform, so the COMIMAGE_FLAGS_32BITPREFERRED flag was invented. For downward compatibility, this flag is not set by itself, but instead modifies the meaning of the COMIMAGE_FLAGS_32BITREQUIRED flag, to allow .NET 4.0 systems to continue to run the executable in 32 bit mode (they simply ignore the new flag) while on ARM systems the system can see that the executable is not x86 specific because the new flag is set.
Finally, when your PE file contains unmanaged exports the ILONLY flag must not be set or the loader will refuse to load the file.