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
The WOW64 layer of Windows allows x86 code to run on the Arm64 version of Windows. x86 emulation works by compiling blocks of x86 instructions into Arm64 instructions with optimizations to improve performance.
Yes you can run x86-64 binaries on arm64.
QEMU can (slowly) emulate any architecture on any other architecture. In this case, they're using QEMU to emulate x86-64 on ARM64. No nesting or Rosetta is needed.
Natively, ARM instructions do NOT run on an x86, and equally so, x86 instructions don't run on an ARM. However, there are emulators in both directions that allow programs compiled for one to run on the other platform in certain circumstances.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With