3

To be able to do cross compiling there's a trick where you copy a static qemu binary into your <different-arch-root-to-be>/usr/bin and when you chroot into that filesystem, which has non-native binaries, magically the binaries are executable by the host cpu, and uname -a and similar claim that you are on the target architecture. The net result is that you can get dead simple cross compiling.

I can imagine a way this might work, but it would require chroot to be qemu aware.

Is this the case? I can't seem to find any documentation as to how this works.

Catskul
  • 1,898
  • 1
  • 14
  • 19

1 Answers1

6

Linux has a mechanism that allows plug-ins to be registered so that the kernel calls an interpreter program when instructed to execute a file: binfmt_misc. Simplifying a bit, when an executable file is executed, the kernel reads the first few bytes and goes like this:

  • Does it start with the four bytes \x7fELF followed by a valid-looking ELF header? If so, use the ELF loader inside the kernel to load the program and execute it.
  • Does it start with the two bytes #! (shebang)? If so, read the first line, parse what's after the #! and execute that, passing the path to the executable as an argument.
  • Does it start with one of the magic values registered through the binfmt_misc mechanism? If so, execute the registered interpreter.

To run foreign-architecture binaries via Qemu, magic values corresponding to an ELF header with each supported architecture are registered through the binfmt_misc mechanism. You can see what is supported by listing the directory /proc/sys/fs/binfmt_misc/ (which is a special filesystem representing the current set of registered binfmt_misc interpreters in the kernel). For example:

cat /proc/sys/fs/binfmt_misc/qemu-arm
enabled
interpreter /usr/bin/qemu-arm-static
flags: 
offset 0
magic 7f454c4601010100000000000000000002002800
mask ffffffffffffff00fffffffffffffffffeffffff

So if an executable /somewhere/foo starts with the specified magic bytes, if you run /somewhere/foo arg1 arg2, the kernel will call /usr/bin/qemu-arm-static /somewhere/foo arg1 arg2.

It is not necessary to use a chroot for this mechanism to work, the executable could be anywhere. A chroot is convenient in order for dynamic executables to work: dynamic executables contain an absolute path to their loader, so if you run e.g. an ARM excutable, it will expect a loader located in /lib. If the loader is in fact located in /different-arch-root-to-be, a chroot to that directory is necessary for the executable to find the loader.

Gilles 'SO- stop being evil'
  • 807,993
  • 194
  • 1,674
  • 2,175