为何在QEMU-system-riscv64中无法运行宿主机编译的RISCV64 ELF程序?
我在x86_64-Ubuntu22.04宿主机上,用riscv64-unknown-linux-gnu-gcc ./test.c -o test编译了如下代码:
#include<stdio.h> int main() { printf("hello world\n"); return 0; }
将可执行文件放入共享目录mnt后,在QEMU内执行./test时终端返回-/bin/sh: ./test: not found。我原以为这是无共享库的二进制文件,宿主机执行ldd test也显示not a dynamic executable。
QEMU启动参数
qemu-system-riscv64 -nographic -m 256M -machine virt -kernel ~/linux-kernel/arch/riscv/boot/Image -append \"root=/dev/vda rw console=ttyS0\" -drive file=rootfs.img,format=raw,id=hd0 -device virtio-blk-device,drive=hd0 -fsdev local,security_model=passthrough,id=fsdev0,path=./host_mnt -device virtio-9p pci,id=fs0,fsdev=fsdev0,mount_tag=hostshare
Busybox根文件系统创建步骤
$ qemu-img create rootfs.img 8g $ mkfs.ext4 rootfs.img $ mkdir rootfs $ sudo mount -o loop rootfs.img rootfs $ cd rootfs $ sudo cp -r ../busyboxsource/_install/* . $ sudo mkdir proc sys dev etc etc/init.d $ cd etc/init.d/ $ sudo touch rcS $ sudo vi rcS #!/bin/sh mount -t proc none /proc mount -t sysfs none /sys /sbin/mdev -s mount -t 9p -o trans=virtio,version=9p2000.L hostshare /mnt $ sudo chmod +x rcS $ sudo umount rootfs
版本信息
riscv64-unknown-linux-gnu-gcc (g2ee5e430018) 12.2.0QEMU emulator version 8.0.0 (v8.0.0)- Linux内核v6.0.0
我困惑为何宿主机编译的ELF无法在QEMU内执行,是否因为rootfs基于Busybox而非Ubuntu rootfs?打算尝试构建基于Ubuntu的rootfs,恳请解答。
核心原因分析
你遇到的not found错误并非文件不存在,而是动态链接器缺失或二进制架构/ABI不匹配——即使ldd显示是静态可执行,也可能存在以下问题:
- 编译未真正生成静态二进制:默认情况下
riscv64-unknown-linux-gnu-gcc可能仍尝试动态链接glibc,需显式指定静态编译参数。 - Busybox根文件系统缺少动态链接器:若二进制为动态链接,Busybox默认不带RISC-V版本的动态链接器,导致系统无法加载执行文件。
- 9p共享目录属性丢失:共享可能丢失文件的可执行权限或ELF属性,需手动确认并修正。
- 内核与用户态ABI不匹配:内核、Busybox、交叉编译器的RISC-V架构参数(如LP64D)需保持一致,否则会出现兼容问题。
解决方案步骤
重新编译静态二进制
显式添加-static参数强制静态编译:riscv64-unknown-linux-gnu-gcc ./test.c -o test -static用
file test验证,输出需包含RISCV 64-bit和statically linked。验证QEMU内文件属性
在QEMU终端执行:ls -l /mnt/test file /mnt/test确认文件有可执行权限,且架构匹配。若权限不足,执行
chmod +x /mnt/test。检查Busybox编译配置
确保Busybox使用同版本的riscv64-unknown-linux-gnu-交叉工具链编译,且开启了mdev等必要功能。尝试Ubuntu根文件系统(可选)
Ubuntu官方的RISC-V根文件系统自带完整的glibc和动态链接器,能更好兼容动态链接二进制,可下载官方镜像替换现有rootfs测试。
内容的提问来源于stack exchange,提问作者beyond

