FatELF: Universal Binaries for Linux.

Overview - Benefits - Demo - Source code - License - Milestones - FAQ


Overview:

FatELF is a file format that embeds multiple ELF binaries for different architectures into one file. This is the Linux equivalent of what Mac OS X calls "Universal Binaries."

The format is very simple: it adds some accounting info at the start of the file, and then appends all the ELF binaries after it, adding padding for alignment. The end of the file isn't touched, so you can still do things like self-extracting .zip files for multiple architectures with FatELF.

FatELF lets you pack binaries into one file, seperated by OS ABI, OS ABI version, byte order and word size, and most importantly, CPU architecture.

Work is focused on GNU/Linux, but this could be applied to most modern Unix systems: the BSDs, Solaris, etc.

Benefits:

Pick your favorite.

It's less likely that people will pack 14 different architectures into one file (although they could, if they like), but this can be very compelling for those dealing with the transition from x86 to x86-64...or whatever the next transition might be.

Demo:

A full FatELF version of Ubuntu 9.04 is available as a vmware virtual machine, to demonstrate the concept. You can find that here.

Source code:

The FatELF tools and patches are stored in a Mercurial repository, here. You can use this command line to get them:

hg clone http://hg.icculus.org/icculus/fatelf

FatELF requires patches to various pieces of a GNU/Linux system. Please see the TODO list, below. We maintain these patches in the Mercurial repository until they have been merged into the upstream project.

License:

Original work (the command line utilities) is zlib-licensed. Patches to other projects are contributed under that project's licensing terms; so Linux kernel patches are GPLv2, FreeBSD patches would be BSD, etc.

Milestones and TODO list:

FAQ:

Questions go to Ryan.

Q: So, wait, isn't this going to take a ton of disk space?
A: Depends. Gluing together two ELF binaries usually doubles the file size. Our proof of concept virtual machine does this for every program in a mostly-default Ubuntu install, and the disk usage does increase quite a bit. There isn't, in most cases, a compelling reason to do this to the entire operating system. Also, in many cases, the space of the ELF files is a tiny fraction of an application's disk footprint.

Q: Can I strip out the bits of a FatELF file that I don't need? If I only run an x86 system, I'd like to delete the PowerPC (or whatever) pieces.
A: Yes. Run fatelf-extract newfilename fatelffilename i386

Q: Does a FatELF binary require more memory than a regular ELF binary?
A: Nope! We decide what chunk of the file applies to the current system and throw the rest away. In most cases, we don't even read the parts we don't need from disk at all.

Q: Do you have to read the entire FatELF file to load it?
A: Nope! Just a few bytes at the start, and then the specific ELF object we want is read directly. The other ELF objects in the file are ignored, so the disk bandwidth overhead is almost non-existent.

Q: So this...adds PowerPC support to my Intel box?
A: No. FatELF is not an emulator, it just glues ELF binaries together. If you have a FatELF binary with PowerPC and Intel records, then PowerPC and Intel boxes will pick the right one and do the right thing, and other platforms will refuse to load the binary, like they would anyway.

Q: Does this let me run 32-bit code on a 64-bit system or vice versa?
A: No. This doesn't let 32-bit and 64-bit code coexist, it just lets them both reside in the file so the platform can choose 32 or 64 bits as necessary.

Q: Do I need to have PowerPC (MIPS, ARM, whatever) support in my FatELF file?
A: No. Put whatever you want in there. The most popular scenario will probably be x86 plus x86_64, to aid in transition to 64-bit systems.

Q: What platforms and processors are supported?
A: Right now work is focused on GNU/Linux, but anything that uses ELF binaries could theoretically be updated to support FatELF without too much trouble. Some other examples of platforms that use ELF are OpenSolaris, FreeBSD, and Haiku. Any processor type the operating system handles is supported. There isn't any processor-specific code in FatELF.

Q: Does this let me run Mac OS X programs on Linux?
A: No. Apple has a file format called "Universal Binaries" that solves roughly the same problem as FatELF, but is otherwise totally different. FatELF does nothing at all to improve compatibility with Mac OS X.

Q: Can I still use regular ELF binaries?
A: Yes. They coexist fine with FatELF ones. A FatELF binary can load ELF shared libraries and vice-versa, too. GDB can debug both at the same time. It's not unreasonable to assume that only a handful of files on a given system will be FatELF.

Q: Can I dlopen() a FatELF shared library?
A: Yes. Assuming there's a supported platform in there, it works like any other shared library.

Q: So FatELF is a universal package format to replace deb or rpm?
A: No. Those things will continue to work as they always have. FatELF is not a package format or package manager.

Q: Doesn't apt/yum/etc solve this problem?
A: No. Each solves it, somewhat, for a given Linux distribution, but even then, there will be places where you want to work outside the package system. Even within these package managers, removing the need for ia32 compatibility packages and /lib64 or /lib32 directories could be extremely compelling.

Q: Couldn't binfmt_misc solve this problem on Linux?
A: No. The Linux kernel (and its binfmt_* modules) only load binaries. Shared libraries are handled in userspace by ld.so. So binfmt_misc would only help you if you didn't care about shared libraries, and we do.

Q: Couldn't a shell script that chooses a binary to launch solve this problem?
A: Sort of. First, it seems needlessly inefficient to launch a scripting language interpreter to run a one-line script that chooses a binary to launch. Second, it adds room for human error. Third, it doesn't handle ABI versions. Fourth, it fails when new processors that could run legacy binaries arrive. If you expected "i386" and "uname -m" reports "i686", it fails. If you didn't know to check for "x86_64" in 1998, your otherwise-functional i386 version won't be run, and the script fails. Doing it cleanly, in well-maintained, centralized code, makes more sense.

Q: Does a FatELF binary statically link the whole kitchen sink into the file?
A: No. Shared libraries (FatELF or otherwise) can be used with FatELF binaries. It's up to the system to handle dynamic loading like it always does, once it finds the ELF record it wants to load inside a FatELF file.

Q: How do you test other platforms when making your FatELF binaries?
A: The same way you would test them if you didn't have FatELF. This just puts them in the same file.

Q: Can you build FatELF binaries with GCC?
A: Not directly, at least not yet. You have to build each ELF binary separately and then glue them together with a command line tool. This can change in the future. Our binutils patch, however, allows GCC to link against a FatELF shared library, though. We have patched both "ld" and the new "gold" linker to support FatELF.

Q: Doesn't this help proprietary/closed-source software?
A: Sure, but it has some serious upsides for 100% Free Software developers and distributions, too. Those behaving badly can behave equally as badly without FatELF.

Q: Doesn't this help trojans and viruses?
A: No. Please do make sure you trust the software you choose to run, though, on any platform and in any format. FatELF doesn't change this situation at all, for better or worse.

Q: Who drew that charming logo?
A: An artist from Gaslamp Games. The Gaslamp crew are currently working on a game called Dungeons of Dredmor. Their website is here.