Reputation: 952
I'm using the Docker container (thewtex/cross-compiler-linux-armv7
) to cross-compile a simple "Hello World" Linux user space C program on an x86_64
system. The target system is a ARMv7 embedded system (in particular a Kobo Aura HD e-reader with stock firmware).
The source code of the program (hello_world.c
) is as follows
#include <stdio.h>
int main(int argc, char *argv[]) {
printf("Hello World!\n");
return 0;
}
Unexpectedly, I can execute the resulting executable on the host system:
andreas@andreas-pc:~/tmp/test$ uname -a && ./hello
Linux andreas-pc 4.5.5-201.fc23.x86_64 #1 SMP Sat May 21 15:29:49 UTC 2016 x86_64 x86_64 x86_64 GNU/Linux
Hello World!
as well as on the target device
[root@(none) onboard]# uname -a && ./hello
Linux (none) 2.6.35.3-850-gbc67621+ #1038 PREEMPT Thu Apr 25 15:48:22 CST 2013 armv7l GNU/Linux
Hello World!
Is there any explanation for this?
For reference, I invoke the compiler using the following set of commands
docker run thewtex/cross-compiler-linux-armv7 > ./dockcross.sh
chmod +x dockcross.sh
For some reason the generated shell script is buggy, I manually have to replace /cross-compiler-base/cross-compiler-linux-armv7/
and /:build/:build:z/
in dockcross.sh
. Now I run
./dockcross.sh arm-linux-gnueabihf-cc hello_world.c -static -o hello
file
returns the following information about the resulting hello
executable
hello: ELF 32-bit LSB executable, ARM, EABI5 version 1 (GNU/Linux), statically linked, for GNU/Linux 2.6.32, BuildID[sha1]=317a9ea164931f614b24e98dec743050e2d7f900, not stripped
Upvotes: 15
Views: 6359
Reputation: 952
There is a mechanism in the Linux kernel called binfmt_misc that can be used to associate arbitrary interpreters with executables. This association can either be based on a magic byte sequence at the beginning of the executable itself, or its file extension (e.g., wine
automatically registers itself for *.exe
files). Interpreters are registered in the kernel by writing to the /proc/sys/fs/binfmt_misc/
sysfs.
On Fedora, the systemd-binfmt
service is responsible for the interpreter registration. It reads a set of configuration files from the /usr/lib/binfmt.d
directory and performs the necessary writes to the sysfs. In the context of the above question, installation of the qemu
emulator-suite will place the corresponding configuration files in this directory. For ARM this file is called qemu-arm
and has the following content:
enabled
interpreter /usr/bin/qemu-arm
flags:
offset 0
magic 7f454c4601010100000000000000000002002800
mask ffffffffffffff00fffffffffffffffffeffffff
This allows to transparently execute statically linked ARM executables on Linux. Thanks to Mark Plotnick for pointing this mechanism out.
Upvotes: 32