How does "arch -arch" work to enable Rosetta and force binary architecture?

67 views Asked by At

When using Rosetta on macOS running on an ARM processor, the arch command can be used to force a wrapped command to execute as a specific architecture. In other words, arch -arch x86_64 mycommand will try to launch mycommand as an x86/Intel program. If mycommand is ARM-only, it will fail; if mycommand is a universal binary, it will be run as x86.

But how does the arch -arch ... command actually work? Specifically, I have these questions:

  • By what mechanism does arch -arch $arch $program select a $arch from a universal binary $program and run it?
  • By what mechanism does arch -arch $arch $program try to run a non-universal binary $program as the selected architecture $arch, causing a failure if the binary doesn't support it?
  • Is it possible for another program to do what arch does here, without shelling out to arch? Even if it's possible-but-not-recommended/a private macOS API, I'm still interested in how it happens.

I'm asking this out of curiosity, not because I need to get around what arch does.

I've tried:

  • Looking into the guts of lipo while making universal binaries. lipo seems to be concatenating binaries for different architectures together in a Mach-O "fat binary" container with some magic bits at the top to indicate what contents are where. This helps a little bit with the first question above, but doesn't help with the second or third.
  • Looking into fat binary parsing tools like mach_object. It seems theoretically possible for me to extract the appropriate sub-binary from a fat binary, dump it to a temp file, and execute it, but that seems like it would have all sorts of problems (CWD would be wrong, writing a file just to launch a program seems wasteful).
0

There are 0 answers