Failed to execute /linuxrc (error -8)

Failed to execute /linuxrc (error -8)

在使用 qemu-system-arm 运行 arm linux 内核时,报了这个错。没有对这个错误进行分析,便开始在网上搜索,搞了一会问题没有解决。

这之后开始注意到 -8 这个返回值,搜索发现这个返回值表示的意思是非法的可执行文件格式,宏名是 ENOEXEC ,是在 exec 系列函数执行时检测的。

进一步操作发现 linuxrc 是用于生成 initramfs 的 _install 目录中的一个文件,我查看该文件发现它是一个软链接,指向 bin/busybox 程序。使用 file 命令查看 busybox 程序的类型,发现 busybox 是 x86-64 架构的程序,它当然不能在 arm 架构中执行喽。

相关的操作如下:

[longyu@debian-10:20:27:16] _install $ ls -l linuxrc 
lrwxrwxrwx 1 longyu longyu 11 12月  7 09:54 linuxrc -> bin/busybox
[longyu@debian-10:20:27:20] _install $ file ./bin/busybox 
./bin/busybox: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 3.2.0, BuildID[sha1]=0f1ea5cdbc5310f4f91da04b44810eec1d091e6a, stripped

重新编译 busybox 之后,使用 file 命令确认编出的是 arm 架构的程序。重新执行 qemu-system-arm 之后发现还是报相同的错误,这就有点奇怪了。我直接执行重新编译的 busybox 程序,竟然发现能够执行,觉得非常奇怪。

下面是我执行的操作与输出:

[longyu@debian-10:20:41:46] busybox-1.30.1 $ file busybox
busybox: ELF 32-bit LSB executable, ARM, EABI5 version 1 (SYSV), statically linked, for GNU/Linux 3.2.0, BuildID[sha1]=71e4953f2c001e0776c66161ecfa3705314e9465, stripped
[longyu@debian-10:20:41:51] busybox-1.30.1 $ ./busybox 
BusyBox v1.30.1 (2019-12-07 20:01:40 CST) multi-call binary.
BusyBox is copyrighted by many authors between 1998-2015.
Licensed under GPLv2. See source distribution for detailed
copyright notices.

Usage: busybox [function [arguments]...]
   or: busybox --list[-full]
   or: busybox --show SCRIPT
   or: busybox --install [-s] [DIR]
   or: function [arguments]...

x86 架构能够直接运行 arm 架构的程序吗?

不同架构的程序,指令集不同,只能在自己的架构上执行,不能在其它架构上直接执行,这一点我确信无疑。那为什么会有上面的现象呢?

搁置了一段时间之后,我想到了 strace 这个命令。我可以通过 strace 命令来追踪下程序执行的过程,结果就发现了一些不同寻常的内容。摘录如下:

readlink("/proc/self/exe", “/usr/bin/qemu-arm-static”, 4096) = 24

man qemu-arm-static 发现这个程序是个模拟器,它能够在相同操作系统的当前平台运行其它平台的二进制程序。这样看来应当是使用了这个模拟器执行了 arm 架构的二进制程序。

使用 readlink 这一行在网上进行搜索,发现了一篇文章,链接如下:

使用 qemu 和 binfmt_misc 在 linux 中运行任意架构的二进制程序

我可以判定 qemu-arm-static 解释执行了 arm 架构的二进制程序,但是需要有一种机制来触发 qemu-arm-static。

看了上面的文章我发现,这个机制是通过安装 qemu-user-binfmt 包启用的。它会在内核中添加 binfmt_misc 入口,可以根据二进制程序中 ELF header 中的信息与 binfmt_misc entry 中注册的每种 binfmt 的信息来匹配,匹配成功后就用相应的模拟器程序解释二进制程序。

binfmt_misc 入口可以通过访问 /proc/sys/fs/binfmt_misc 获取到。

下面是 qemu-arm 的 binfmt_misc entry 的内容:

[longyu@debian-10:21:51:44] etc $ cat /proc/sys/fs/binfmt_misc/qemu-arm
enabled
interpreter /usr/bin/qemu-arm-static
flags: OCF
offset 0
magic 7f454c4601010100000000000000000002002800
mask ffffffffffffff00fffffffffffffffffeffffff

可执行文件的 ELF header 中记录着 ELF magic、architecture code 等信息,通过获取这些信息就可以与 binfmt_misc 中注册的项目进行匹配,匹配成功则用相应的解释器解释执行二进制程序。

这里我执行的 arm 程序就是用 qemu-arm-static 来解释执行的,从 strace 的输出中可以确认这一点。

这样就可以排除可执行文件格式的问题,那真正的问题又是什么呢?

initramfs 的问题

在执行 menuconfig 是我进行了如下配置:
Initial RAM filesystem and RAM disk
这里指定了一个 _install 目录,是 initramfs 文件系统制作的源文件存放目录。由于我不清楚这项配置的功能,我以为是在 qemu-system-arm 运行的时候才会被用到,就只用重新编译的 busybox 替换了 _install 下的 busybox 程序,然后重新执行 qemu-system-arm 程序,问题没有得到解决。

这之后我发现这里针对 initramfs 设定的 _install 目录是在内核编译过程中使用的,内核会使用 _install 中的文件生成 initramfs 文件系统并编译到内核镜像 bzImage 中。

于是我重新编译了内核,这次我注意到了如下信息:

 GEN     usr/initramfs_data.cpio.gz
 GZIP    kernel/config_data.gz
 AS      usr/initramfs_data.o

从上面的信息中可以确定编译时确实将生成的 initramfs 文件系统的数据编到了内核中。

这之后重新执行 qemu-system-arm 命令,执行成功

  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值