8

It's been baffling me how the "AnyCPU" feature in .NET works: It loads the executable as native 32-bit if the system is 32-bit, and as 64-bit if the system is 64-bit (which you can easily confirm with Task Manager). So obviously, this isn't impossible.

The question is, how exactly did Microsoft do this? Windows originally didn't know about the .NET framework, so the Windows PE Loader can't possibly look for any extra features in PE headers for the CLR header; this feature must have been added by some sort of kernel-mode extension. But the .NET framework seems to install no such thing... I'm at a complete loss at how the same executable can be native 32-bit and 64-bit at the same time, especially since a disassembly of mscoree.dll doesn't even show references to undocumented native functions.

Does anyone have any knowledge and/or reasonable guesses as to how this was done? It's obviously possible (so no saying things like "it's not possible"), and it makes me want to try to write a native cross-platform EXE...


Edit:

As a side note, consider how you can't run 32-bit executables in a 64-bit Windows PE environment... there's got to be some way to extend or modify the PE loader with some sort of "plugin", right?

user541686
  • 205,094
  • 128
  • 528
  • 886
  • There are some programs (e.g. Process Explores) which do this my distributing a 32-bit executable which *launches* a 64-bit image if possible. E.g. is an "AnyCPU" executable ever anything but a 32-bit PE? –  Jan 10 '11 at 03:55
  • @pst: I'm completely aware of those, but no, they're different. AnyCPU executables are 64-bit from the moment they start on 64-bit OS's -- there's no unpacking and there's nothing like "Let's JIT this bytecode code into 64-bit and then restart the 64-bit process." That's what leaves me baffled. – user541686 Jan 10 '11 at 03:59

2 Answers2

5

Your question is based on a misunderstanding. Here's the mistake:

Windows originally didn't know about the .NET framework

Actually, since Windows XP, Windows IS aware of the .NET executable format. And XP was the first version of Windows to support 64-bits.

So the PE header is marked 32-bit and the native import table references the 32 bit mscoree, which on Windows 2000 and earlier, causes 32-bit .NET to be loaded. DllMain for mscoree starts JITting the application code and modifies the entrypoint for the main application.

Windows XP and later, being aware of the .NET metadata, recognizes that it is AnyCPU and loads the appropriate framework.

Here's probably more than you ever wanted to know about the process.

So no, there is no native AnyCPU exe. Although you can embed a 16-bit DOS program in a 32-bit PE, you can't have a combined 32-bit and 64-bit .exe

Ben Voigt
  • 277,958
  • 43
  • 419
  • 720
  • Didn't the .NET framework come out *after* the release of XP (at least, that's what I thought I remembered)? I thought [XP was released in 2001](http://en.wikipedia.org/wiki/Windows_xp) and [.NET in 2002](http://en.wikipedia.org/wiki/.NET_Framework)... – user541686 Jan 10 '11 at 04:15
  • @Lambert: The development periods overlapped, .NET development started something like 5 years before the initial release in 2002, so Microsoft has plenty of time to put the hooks into XP. And as I said, Windows 2000 is only 32-bit. Anyway, it's the release date of Windows XP 64-bit edition, several years later, that you should be considering, since it's the first version that needed this "magic". – Ben Voigt Jan 10 '11 at 04:17
  • Ah... that explains it. (And yeah, sorry I removed the Windows 2000 part about my comment right before you posted, since I remembered it didn't have 64-bit.) Not the answer I was looking for, but definitely seems correct; thanks! :) – user541686 Jan 10 '11 at 04:21
  • @Lambert: Added two links you might enjoy reading for further details. – Ben Voigt Jan 10 '11 at 04:29
  • @Ben: I'd already read the first link, but the second one was new. At first I thought this was going to tell me about the WOW64 thunks and all that, and good thing I didn't complain about already knowing those because the .NET information was definitely new and useful. Thanks for posting these! Wish I could give another +1. :) – user541686 Jan 10 '11 at 04:40
  • Windows XP 64-Bit Edition was released in 2001 at the same time as 32-bit XP (http://en.wikipedia.org/wiki/Windows_XP_64-bit_Edition#Windows_XP_64-Bit_Edition), but it probably didn't matter because I don't think a 64-bit CLR was released until 2005. – Gabe Jan 10 '11 at 05:04
  • @Gabe: But that was the Itanium one. And yeah, 64-bit wasn't supported until .NET 2. Read the linked articles for the gory details. – Ben Voigt Jan 10 '11 at 05:20
  • XP 64 bit did not come out in 2001. What's more XP 64 cannot be considered the same as XP. It was version 5.2, based off server 2k3 code. They called it XP for marketing reasons. – David Heffernan Mar 04 '11 at 20:11
  • @David: Server 2k3 is pretty much the Windows XP kernel with SP1 pre-installed. Just like Windows 2000 Pro and Server share a kernel, and Vista and Windows 2008, and Win7 and Win 2008R2. – Ben Voigt Mar 05 '11 at 00:04
  • @ben actually 2k3 and xp were a different codebase and it was only vista that brought client and server back together. XP 64 and 2k3 come off the same branch. – David Heffernan Mar 05 '11 at 07:56
  • @David: In any case, Windows 5.1, which we both agree is properly called Windows XP, contained loader support for .NET metadata. – Ben Voigt Mar 05 '11 at 15:34
  • @Ben True enough. But I think it wasn't until 5.2 (2k3, XPpro for x64) that it even could have known about 64 bit. Anyway, I'm just indulging in a spot of mild pedantry!! ;-) – David Heffernan Mar 05 '11 at 15:44
  • In fact, VS2002 was released only 3 months after XP launched. – Yuhong Bao Apr 29 '13 at 20:01
4

You actually can have x64 code in an x86 executable if the system has a WOW64 emulation layer (Windows Vista+, dunno about XP). http://vxheavens.com/lib/vrg02.html

I have tested this technique and it works on Win7 as well as WinVista. I wrote a little stub in assembly to resolve imports and load up some C code that was compiled for AMD64.

Microsoft just says you can't transition back and forth because they might change it, but I doubt this will change until the underlying architecture changes to allow something like 128 bit to run as well... at that point I doubt WOW64 will be around :), WOW128 ftl.