When a managed application is built on Visual Studio , we get four options to choose for a platform .Lets discuss these options in detail .
X86 is the generic name for all Intel x86 32 bit architectures. If you build your application using x86 switch , your binary will run as 32 bit process. Technically speaking a pure managed application is compiled into MSIL .So when this IL is jitted or you convert IL image to native image using NGEN, 32 bit code will be generated .And if an application is a mix mode application, the native code generated will be 32 bit.
X64 refers to 64 bit descendant of x86 family. There are two major 64 bit architectures available ,one is x64 and other is IA64. These architectures are totally different architectures .Following are major differences in terms of compatibility with x86:
So if you use x64/Itanium, binary generated will run as a 64 bit process. Again if it is pure managed application is compiled into MSIL .So when this IL is jitted or you convert IL image to native image using NGEN, 64 bit code will be generated .And if application is a mix mode application native code generated will be 64 bit.
3) Any CPU
If you use this option code generated can run on any platform. Pure managed code can only have this option. To be very precise, It will compiled into 32 bit code on a 32 bit machine and into 64 bit code on 64 bit machine.
Your application’s manifest contains a field corflags. The value of this filed, among other things determines whether IL will be converted to a 32 bit code or 64 bit code. Corflags field is a bit field and, Its following are of interest to us :
1) 0x1(IL_ONLY) It means that assembly’s code is IL_ONLY that is it is pure IL thus it can be compiled to either 32 bit or 64 bit
2) 0x2(32BIT_ONLY) means that assembly’s code must be compiled to 32 bit code and cannot be compiled to 64 bit.
3) 0x8 means assembly is signed.
Open assembly file in ILDASM and have a look at its manifest. Value of corflags field can be found at bottom of the manifest file. A value of 0x3 means assembly contains pure IL but it can be compiled only into 32 bit code. 0xb means assembly is signed contains IL only code with restriction that it can be compiled only as 32 bit code.
Note on opening the assembly in dumpbin utility one finds that x64 and IA64 images generated by the compiler with /platform:x64 or :IA64 are PE32+ images (the 64bit extension to PE32) whereas x86 and MSIL(IL_ONLY) are PE32 images (otherwise they wouldn’t work on 32bit OS’s). When the OS loader comes across a managed image the first thing it does is hand it to some CLR code called the shim (mscoree.dll) which among other things modifies MSIL images in memory to turn them into PE32+ images before handing them back to the OS loader to get the OS loader to load your app as a 64bit process.
If your assembly is running as a 32 bit process it cannot load a 64 bit dll and vice versa. If it tries to load a 64 bit dll we get a BadImageFormat Exception. Technically speaking a 32 bit process should never load a 64 bit dll. To be very precise the only 64 bit dlls that a 32 bit process can load are WOW dlls and ntdll.dll which are essential for it to run on a 64 bit machine. Following is a brief description of WOW64 dlls.
· Wow64Cpu.dll provides x86 instruction emulation on Itanium processors. It executes mode-switch instructions on the processor. This DLL, on all WOW64 variants, abstracts out the code needed to execute x86 instructions. On IA64, it can either use the IA64 hardware or software emulator. On x64 it is responsible for the mode-switch via JMP FAR.
If an assembly on loading is throwing a BadImageFormat Exception, first thing to do is check the corflags field. Typically
1) Open assembly’s manifest in ildasm tool. Check its corflags field.
2) If its value is x64 , your assembly has a dependency on a 32 bit dll. Either change the dll to 64 bit or modify corflags field to x86.
3) If its value is Any CPU , and you are running on a 64 bit machine , it is same scenario as described in 2.
Most of the times above two are the only reasons. In order to modify corflags field
1) Either use a utility known as corflags in order to change the corflags field without recompiling the assembly. Note that however if assembly is signed it needs to be resigned which can be done using sn tool.
2) Or best option is to recompile your application with appropriate /platform flag.