-->

Fat Mach-O Executable Multi-purpose?

2020-05-09 09:55发布

问题:

I am currently working with Mach-O Executables on my Mac and A question just came across me, Can a single Fat Mach-O Executable file have multiple purposes? Eg.

Could I Have a single Mach-O Executable File with a Fat Header specifying 2 Executables:

Executable 1 : This executable could be a Dynamic Library allowing Its code to be loaded in external applications.

and

Executable 2 : This executable could be an Executable allowing It to be independently launched through Terminal or as an Application.

I just want to know, could this be possible to have 2 Executables with completely different functions inside a single Mach-O Binary File?

回答1:

Yes it is possible, but hardly useful. Before I get to why, here's how to create one:

Take this C file:

#ifdef __LP64__
int main(void)
#else
int derp(void)
#endif
{
    return 123;
}

Compile it as a 64-bit executable and a 32-bit shared library:

gcc -o t t.c -Wall
gcc -m32 -o t.dylib -Wall t.c -shared

And smash them together:

lipo -create -output t.fat t t.dylib

Now, why is that supposed to be not useful?
Because you're limited to one binary per architecture, and you have little to no control over which slice is used.
In theory, you can have slices for all these architectures in the same fat binary:

  • i386
  • x86_64
  • x86_64h
  • armv6
  • armv6m
  • armv7
  • armv7s
  • armv7k
  • armv7m
  • arm64

So you could smash an executable, a dylib, a linker and a kernel extension into one fat binary, but you'd have a hard time getting anything useful out of it.
The biggest problem is that the OS chooses which slice to load. For executables, that will always be the closest match for the processor you're running on. For dylibs, dylinkers and kexts, it will first be determined whether the process they're gonna be loaded into is 32- or 64-bit, but once that distinction has been made, there too you will get the slice most closely matching your CPU's capabilities.

I imagine back on Mac OS X 10.5 you could've had a 64-bit binary bundled with a 32-bit kext that it could try and load. However, outside of that I cannot think of a use case for this.