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.