Windows – How does OSX run 64bit Binaries while running on a 32bit Kernel

32-bit64-bitmacosunixwindows

I have recently figured out that Mac OS X actually CAN run 64bit (x64) applications even if x86 kernel is loaded. That was shocking for me for a first time.

But then I've realized that it is really weird if system is up and running under x64 compatible CPU can't run x64 applications, no matter what kernel managing the processes. Is it really so hard? Just load damn app into the memory and set up the CPU operation pointer to the first byte, easy as pie!

The one and only barrier to do that, as I could imagine, is some kind of "executable headers". Unfortunately, I am not very comfortable with Windows architecture and binary structure, so I need more explanation here.

De facto UNIX-like OS binary header standard ELF has it's brother ELF64, which (as the document here describes) doesn't have much differences with ELF32, but even though 32bit kernels aren't able to run x64 code. Yes, this program is likely linked to x64 libraries and lets imagine we just copied and pasted them right into /usr/lib64 folder. But I'm pretty sure that doesn't help, why?

And finally, what is so special about Mac OS X kernel so it doesn't worry about program instruction set used? Does Mac OS X have some universal and suitable for both kernels executables header, so it just can load app into the memory and say to CPU "execute right from here, I don't mind what stands for that"?

P.S.: I really thought much about where to place this question: on the stackoverflow.com or superuser.com, and decided to place here, because the topic is likely more OS-specific thing.

Best Answer

The real question would be why some other operating systems can't run 64-bit binaries on a 32-bit kernel. There is no fundamental reason why it wouldn't be possible. The underlying processor architecture supports both a 64-bit instruction set (amd64 a.k.a. x86-64) and a 32-bit instruction set (i386), and there is no restriction on the two being used together (in particular, there isn't a “64-bit mode” that's separate from a “32-bit mode”; there's a single long mode, which allows instructions from both the i386 and the “native” amd64 set).

Running 64-bit applications on a 32-bit kernel does require a little more work inside the kernel, because it must manage 64-bit pointers to user space together with 32-bit pointers to kernel space. Most if not all pointers passed around in the kernel are either known to be to kernel space or known to be to user space, so it isn't a problem if they're different size. The main difficulty is foregoing the possibility of having a universal pointer type that has separate ranges of values for process memory, kernel memory and memory used by various pieces of hardware (including RAM), but this isn't possible in recent 32-bit kernels on PC-class hardware anyway (if you have 4GB or more of RAM, or want to map 2GB of RAM plus 2GB of process space plus kernel memory and more, you need to be able to map more than 32 bits' worth of addresses anyway).

According to the Wikipedia article that you cite, OSX had the ability to run amd64 processes on amd64 processors before it had a 64-bit kernel. Solaris also indifferently mixes i386 and amd64 executables on amd64 processors, regardless of whether the kernel is 32-bit or 64-bit (both are available).

Other operating systems can run i386 processes on a (64-bit) amd64 kernel, but not amd64 processes on a 32-bit kernel, for example Linux, FreeBSD, NetBSD and Windows. Yet other operating systems treat amd64 and i386 as completely different architectures, for example OpenBSD.

Related Question