Fat binary

The use of fat binaries is not common in operating system software; there are several alternatives to solve the same problem, such as the use of an installer program to choose an architecture-specific binary at install time (such as with Android multiple APKs), selecting an architecture-specific binary at runtime (such as with Plan 9's union directories and GNUstep's fat bundles),[2][3] distributing software in source code form and compiling it in-place, or the use of a virtual machine (such as with Java) and just-in-time compilation.

Applications released as "fat binaries" took up more storage space, but they ran at full speed on either platform.

[7][8][9] Fat binaries were larger than programs supporting only the PowerPC or 68k, which led to the creation of a number of utilities that would strip out the unneeded version.

The version of the GNU Compiler Collection shipped with the Developer Tools was able to cross-compile source code for the different architectures on which NeXTStep was able to run.

Apple promoted the distribution of new applications that support both PowerPC and x86 natively by using executable files in Multi-Architecture Binary format.

[14][15] As the opcodes of the two processor families are not compatible, attempting to start a program under the wrong operating system leads to incorrect and unpredictable behaviour.

In order to avoid this, some methods have been devised to build fat binaries which contain both a CP/M-80 and a DOS program, preceded by initial code which is interpreted correctly on both platforms.

Similar, the CP/M assembler Z80ASM+ by SLR Systems would display an error message when erroneously run on DOS.

In order to indicate this, the first byte in the header is set to magic byte C9h, which works both as a signature identifying this type of COM file to the CP/M 3.0 executable loader, as well as a "RET" instruction for 8080-compatible processors which leads to a graceful exit if the file is executed under older versions of CP/M-80.

One program known to do this was WordStar 3.2x, which used identical overlay files in their ports for CP/M-86 and MS-DOS,[27] and used dynamically fixed-up code to adapt to the differing calling conventions of these operating systems at runtime.

[29] This is fixed up dynamically by the operating system when the driver loads (typically in the DOS BIOS when it executes DEVICE statements in CONFIG.SYS).

[31] Likewise, the PC DOS and DR-DOS system files IBMBIO.COM and IBMDOS.COM are special binary images loaded by bootstrap loaders, not COM-style programs.

[33][32][34][31] Additionally, the message is specifically crafted to follow certain "magic" patterns recognized by the external NetWare & DR-DOS VERSION file identification utility.

[31][32][nb 7] A similar protection feature was the 8080 instruction C7h ("RST 0") at the very start of Jay Sage's and Joe Wright's Z-System type-3 and type-4 "Z3ENV" programs[35][36] as well as "Z3TXT" language overlay files,[37] which would result in a warm boot (instead of a crash) under CP/M-80 if loaded inappropriately.

This control character will be interpreted as "soft" end-of-file (EOF) marker when a file is opened in non-binary mode, and thus, under many operating systems (including the PDP-6 monitor[38] and RT-11, VMS, TOPS-10,[39] CP/M,[40][41] DOS,[42] and Windows[43]), it prevents "binary garbage" from being displayed when a file is accidentally printed at the console.

[citation needed][48][49] Although the Portable Executable format used by Windows does not allow assigning code to platforms, it is still possible to make a loader program that dispatches based on architecture.

This is because desktop versions of Windows on ARM have support for 32-bit x86 emulation, making it a useful "universal" machine code target.

Fatpack is a loader that demonstrates the concept: it includes a 32-bit x86 program that tries to run the executables packed into its resource sections one by one.

[52] The following approaches are similar to fat binaries in that multiple versions of machine code of the same purpose are provided in the same file.

Since 2007, some specialized compilers for heterogeneous platforms produce code files for parallel execution on multiple types of processors, i.e. the CHI (C for Heterogeneous Integration) compiler from the Intel EXOCHI (Exoskeleton Sequencer) development suite extends the OpenMP pragma concept for multithreading to produce fat binaries containing code sections for different instruction set architectures (ISAs) from which the runtime loader can dynamically initiate the parallel execution on multiple available CPU and GPU cores in a heterogeneous system environment.

Its LLVM-based compiler NVCC can create ELF-based fat binaries containing so called PTX virtual assembly (as text) which the CUDA runtime driver can later just-in-time compile into some SASS (Streaming Assembler) binary executable code for the actually present target GPU.

In addition, the library loader in glibc supports loading from alternative paths for specific CPU features.

[67] A similar, but byte-level granular approach originally devised by Matthias R. Paul and Axel C. Frinke is to let a small self-discarding, relaxing and relocating loader embedded into the executable file alongside any number of alternative binary code snippets conditionally build a size- or speed-optimized runtime image of a program or driver necessary to perform (or not perform) a particular function in a particular target environment at load-time through a form of dynamic dead code elimination (DDCE).

Apple Universal binary logo
FatELF logo