ARM Linux 可执行文件神秘地运行在 x86_64 上
ARM Linux executable mysteriously runs on x86_64
我正在使用 Docker 容器 (thewtex/cross-compiler-linux-armv7
) 交叉编译一个简单的 "Hello World" Linux 用户 space C 程序 x86_64
系统。目标系统是一个 ARMv7 嵌入式系统(特别是带有库存固件的 Kobo Aura HD e-reader)。
程序源码(hello_world.c
)如下
#include <stdio.h>
int main(int argc, char *argv[]) {
printf("Hello World!\n");
return 0;
}
出乎意料,我可以在主机系统上执行生成的可执行文件:
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!
以及在目标设备上
[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!
有什么解释吗?
作为参考,我使用以下一组命令调用编译器
docker run thewtex/cross-compiler-linux-armv7 > ./dockcross.sh
chmod +x dockcross.sh
由于某些原因,生成的 shell 脚本有问题,我必须手动替换 dockcross.sh
中的 /cross-compiler-base/cross-compiler-linux-armv7/
和 /:build/:build:z/
。现在我运行
./dockcross.sh arm-linux-gnueabihf-cc hello_world.c -static -o hello
file
returns 有关生成的 hello
可执行文件的以下信息
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
Linux 内核中有一种称为 binfmt_misc 的机制,可用于将任意解释器与可执行文件相关联。这种关联可以基于可执行文件本身开头的神奇字节序列,也可以基于其文件扩展名(例如,wine
自动为 *.exe
文件注册自身)。解释器通过写入 /proc/sys/fs/binfmt_misc/
sysfs 在内核中注册。
在 Fedora 上,systemd-binfmt
服务负责解释器注册。它从 /usr/lib/binfmt.d
目录读取一组配置文件并对 sysfs 执行必要的写入。在上述问题的上下文中,安装 qemu
仿真器套件会将相应的配置文件放在该目录中。对于 ARM,此文件称为 qemu-arm
并具有以下内容:
enabled
interpreter /usr/bin/qemu-arm
flags:
offset 0
magic 7f454c4601010100000000000000000002002800
mask ffffffffffffff00fffffffffffffffffeffffff
这允许在 Linux 上透明地执行静态链接的 ARM 可执行文件。感谢 Mark Plotnick 指出这个机制。
我正在使用 Docker 容器 (thewtex/cross-compiler-linux-armv7
) 交叉编译一个简单的 "Hello World" Linux 用户 space C 程序 x86_64
系统。目标系统是一个 ARMv7 嵌入式系统(特别是带有库存固件的 Kobo Aura HD e-reader)。
程序源码(hello_world.c
)如下
#include <stdio.h>
int main(int argc, char *argv[]) {
printf("Hello World!\n");
return 0;
}
出乎意料,我可以在主机系统上执行生成的可执行文件:
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!
以及在目标设备上
[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!
有什么解释吗?
作为参考,我使用以下一组命令调用编译器
docker run thewtex/cross-compiler-linux-armv7 > ./dockcross.sh
chmod +x dockcross.sh
由于某些原因,生成的 shell 脚本有问题,我必须手动替换 dockcross.sh
中的 /cross-compiler-base/cross-compiler-linux-armv7/
和 /:build/:build:z/
。现在我运行
./dockcross.sh arm-linux-gnueabihf-cc hello_world.c -static -o hello
file
returns 有关生成的 hello
可执行文件的以下信息
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
Linux 内核中有一种称为 binfmt_misc 的机制,可用于将任意解释器与可执行文件相关联。这种关联可以基于可执行文件本身开头的神奇字节序列,也可以基于其文件扩展名(例如,wine
自动为 *.exe
文件注册自身)。解释器通过写入 /proc/sys/fs/binfmt_misc/
sysfs 在内核中注册。
在 Fedora 上,systemd-binfmt
服务负责解释器注册。它从 /usr/lib/binfmt.d
目录读取一组配置文件并对 sysfs 执行必要的写入。在上述问题的上下文中,安装 qemu
仿真器套件会将相应的配置文件放在该目录中。对于 ARM,此文件称为 qemu-arm
并具有以下内容:
enabled
interpreter /usr/bin/qemu-arm
flags:
offset 0
magic 7f454c4601010100000000000000000002002800
mask ffffffffffffff00fffffffffffffffffeffffff
这允许在 Linux 上透明地执行静态链接的 ARM 可执行文件。感谢 Mark Plotnick 指出这个机制。