As promised, what is the WOW64 and what does it mean to managed apps that you run on 64bit machines?
So, what is the WOW64? If you already have a firm grasp please feel free to skip these first few paragraphs to the section titled “Break in here for the .Net perspective” .
When I went and Google’d a bit to see if anyone had a convincing answer out there what I seemed to find instead was confusion. Note this article titled “WOW64 for AMD Released to the Public”
. With a firmer understanding of what the WOW64 is the fact that this headline is misleading would not have escaped that journalist. So lets start with the name:
WOW64 = Windows On Windows64
It might be more appropriately written “Windows32 On Windows64” but then the acronym isn’t nearly as cool. Basically it is a layer of code that allows for 32bit processes to run just like they were running on a 32bit system under a 32bit OS (e.g. your normal managed app running on the CLR on WindowsXP on a Pentium 4) even though in reality they are running on a 64bit OS. In fact you can find a good indicator of this by looking in your WINDOWS directory where now you will not only find the misnamed SYSTEM32 directory (which holds the 64bit dlls for the 64bit OS) but also the SYSWOW64 directory which holds 32bit versions of dlls for the virtual 32bit OS.
<historical note> I believe that there was a WOW32 effort as well during the move from Win16 to Win32. That move was accompanied by a significant change in programming model as the Win32 API was introduced (The Win16 stuff still lives in WINDOWS\SYSTEM). Generally the Win64 platform uses the Win32 API with platform specific data types (pointers and such) just expanded to fit the new hardware. This is why Windows decided to stick with the SYSTEM32 directory as the primary home for Win64 dlls even though the name can be misleading. This entry and discussion on Raymond’s blog is an interesting read that talks about the joys of backwards compatibility and Win16. </historical note>
You can imagine (and not be too far off) that once you’ve been kicked off by the loader as a 32bit process WINDOWS\SysWow64 gets aliased (for your purposes) to WINDOWS\System32. This has side effects, like the fact that one of my favorite little text editors (EmEditor) which is 32bit can’t find files in the real WINDOWS\System32 directory when running in the WOW64 on my 64bit boxes (it took me a while to figure out why I couldn’t find a couple of scripts that I knew for sure I had dropped in there). There are other parts of the system which are also split into two parts, most notably the registry, unfortunately I don’t know nearly enough about the technical details of that split to discuss it intelligently here.
Under the hood Windows is doing a lot of work to make sure things continue to look just like you’re on a 32bit box and this generally pays off in app compatibility. As would be expected however there is a performance hit that you take for running in this mode, it is an especially heavy hit on IA64 where in the current implementation the x86 instruction set is emulated with software. It is worth noting however that it does work pretty darn well, and the x86 CLR that we’ll be shipping to Win64 users to run in the WOW64 is the same build as that which we ship to x86 users (we just have to mess with the installer a bit). Other large apps can run in the WOW64 and be quite snappy on 64bit Extended hardware platforms (read:AMD64, IA32e) which can natively run the 32bit x86 instructions in a special more of the processor. I've played with VS for instance running on an AMD64 machine like this and it's great.
It is important to understand that once you’re loaded up in the WOW64 you’re a 32bit process and there’s no turning back. You have to use 32bit dlls all around. On the other hand, once you start up 64bit you’re 64bit, no 32bit dlls allowed. So, unfortunately this is not one of those things you can slowly transition. It is possible to kick off another process of a different bitness from your own and communicate with it through RPC or out of proc COM, and this can serve as a transition for some. But hopefully over the next couple months I’ll help to convince you that the move to running native as a 64bit process is going to be worth it.
>> Break in here for the .NET perspective <<
So, what does this mean for .Net and the CLR? The Whidbey CLR will be available in 32bit and 64bit versions with the 64bit version supporting x64 (AMD64/IA32e) and IA64 (Itanium). And the current plan is that when you install the 64bit CLR on a machine we’ll slap down the 32bit version of Whidbey at the same time. Yes, you read that right – your 64bit machine will end up with two copies of the runtime. The 32bit version will be installed in \WINDOWS\Microsoft.Net\Framework just as it would on a native 32bit machine whereas the 64bit version ends up in \WINDOWS\Microsoft.Net\Framework64, no rocket science here, though the GAC issues can be interesting (I’ll talk about these for sure in a later blog entry). Why do we need two frameworks on the machine you might ask? Isn’t one of the cool things about compiling to IL that the JIT takes care of the hardware specific stuff and your code just automatically takes advantage of the new platform it is there?
Well… There are many cases where you just want your code to “float up” to the new platform and run as native 64bit code. In fact, if you’re writing a fully managed app today chances are good that this is what you desire. But, there are still a lot of apps that use PInvoke, COM Interop to inproc servers (including using VB libraries pre-.Net) or APIs that won’t initially be available in 64bit which could break horribly. Remember that once you’re process is started as 64bit that’s it. Trying to load and execute code from a 32bit dll at that point is undefined and your process will certainly die a quick and painful death. While it is true that most of the dlls that come with Windows will be available on both 32bit and 64bit platforms many custom unmanaged code out there hasn’t yet made the jump. The plus side to not going to a new Win64 API is that if you define your PInvoke signatures correctly, most of the Win32 API is still there in a 64bit version and you’ll just pick up the new dlls and run native! In cases where you’re using some unmanaged code that you have no control over and isn’t available in a 64bit version it behooves you to specify that your app requires that it be run in a 32bit process.
How do you specify that? Well, fundamentally it is specified in the CLR headers of your PE image (the format of your dll or exe on disk and in memory). Realistically it is set at compile time (e.g. with C# use the /platform switch). Your exes and dlls can be marked one of four things: MSIL, x86, x64, IA64 (names vary depending on who you talk to). Let’s start out with the obvious ones:
x86: on a 32bit platform this will just run, no hassles. On a 64bit platform this will get started up as a 32bit process in the WOW64 running under the 32bit CLR. You’ll load 32bit .Net FX images out of the GAC (like MSCorLib, System.Web, System.Windows.Forms, etc..). Your code will be JITted by the x86 JITter and will run (in emulation on IA64) as x86 code.
x64: on a 64bit x64 platform this will run as a 64bit process. On a IA64 or x86 box you’ll get a BadImageFormatException. When you’re running as a 64bit process your image will be JITted 64bit native, we’ll pull 64bit images out of the GAC (be it by loading a 64bit native image that has been previously ngen’d or grabbing IL out of the GAC and JITting it at runtime to be 64bit).
IA64: like x64, but swap x64 for IA64.
Then there is MSIL (or “anycpu” as I think the C# compiler switch goes, some people will also refer to this as agnostic or neutral), this indicates that the code here really isn’t processor specific, on a 32bit platform it will get loaded up as a 32bit process and on a 64bit platform it will float up to a 64bit process and run under the 64bit CLR. This is rather important to know as this is currently the default for applications that are compiled using Whidbey compilers (disclaimer: this is still being hotly debated as to whether or not it is the right default, “currently” in this case means if you look at the build that I’m working with on my box on 3/11/04, what we ship may/may not reflect that).
<1.0&1.1 Note> As for 1.0/1.1 apps that are deployed onto a 64bit box, right now we’re probably going with a model that assumes that those assemblies (which didn’t know about bitness) will run in a 32bit process under the WOW64 as if they had been compiled with /platform:x86. The thought process leading us this direction is that we’d prefer to be conservative and by running 1.0/1.1 apps in the WOW64 we ensure that they don’t run into bitness issues that their developers might not have anticipated as it wasn’t part of the .NET world when they were being developed.
Under that model, if you do want your application to run in a 64bit process you’ll need to explicitly recompile it with one of the Whidbey compilers which know about bitness. Then (currently, see disclaimer above) if you don’t specify /platform:x86 your app will run 64bit when/if it is deployed to an x64 or IA64 box. </1.0&1.1 Note>
<GEEK> There is actually some interesting stuff that goes on under the covers here as well, that is if you’re interested in PE images and loader magic, x64 and IA64 images generated by the compiler with /platform:x64 or :IA64 will be PE32+ images (the 64bit extension to PE32) whereas x86 and MSIL are PE32 images (other wise 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 we call the shim (mscoree.dll) which interrogates the image, potentially makes some fixups and gives it back to the OS loader to let the OS then kick it off and trigger the actual runtime to start up. But, to get the OS loader to load your app as a 64bit process you have to give it a 64bit image, so in the shim on 64bit machines we will actually modify MSIL images in memory to turn them into PE32+ images before handing them back to the OS loader. This then in turn causes the loader to start up the right (64bit) runtime. </GEEK>
>> End .NET perspective <<
Recap: So, what have I talked about?
- WOW64 isn’t the OS per se, but a subset of the Win64 OS which enables a 32bit application to run inside of a 32bit process on a 64bit OS while using 32bit system dlls and such.
- Whidbey CLR will include both 32bit and 64bit versions, both of which will be installed on 64bit machines. This allows both 32bit and 64bit managed applications to run in bitness correct native process depending on how the assemblies are tagged at compile time.
- Once a process is started up as either 32bit or 64bit all of the dlls/assemblies that are loaded into that process have to be compatible with that bitness. There is a significant complexity for instance in the GAC to make this possible for .NET FX images (I promise to talk more about that in a later blog entry).
- If you have a 32bit managed app which has dependencies on 32bit unmanaged code then you’ll need to either find a 64bit version of the unmanaged code or tag your managed app as x86 at compile time to make sure that you don’t float up to a native 64bit process. This will result in you having to live with your process running under the WOW64.