How to solve “error while loading shared libraries” when trying to run an arm binary with qemu-arm?
我正在使用qemu,qemu-user和gnueabi工具链运行Linux Mint 14。 我用arm-linux-gnueabi-gcc test.c -o test编译了test.c。
当我尝试运行qemu-arm /usr/arm-linux-gnueabi/lib/ld-linux.so.3 test
我收到一条错误消息:test: error while loading shared libraries: test: cannot open shared object file: No such file or directory。 正如我之前尝试过的那样,运行qemu-arm test会给出/lib/ld-linux.so.3: No such file or directory
但是,该文件确实存在并且可以访问。
1 2 3 4 5 6 7 8 9
| $ stat /usr/arm-linux-gnueabi/lib/ld-linux.so.3
File: `/usr/arm-linux-gnueabi/lib/ld-linux.so.3' -> `ld-2.15.so'
Size: 10 Blocks: 0 IO Block: 4096 symbolic link
Device: 801h/2049d Inode: 4083308 Links: 1
Access: (0777/lrwxrwxrwx) Uid: ( 0/ root) Gid: ( 0/ root)
Access: 2013-04-22 16:19:48.090613901 -0700
Modify: 2012-09-21 08:31:29.000000000 -0700
Change: 2013-04-22 15:58:41.042542851 -0700
Birth: - |
有谁知道我如何让qemu运行arm程序而不必模拟整个arm Linux内核?
test.c是
1 2 3 4 5
| #include <stdio.h>
int main() {
printf("this had better work\
");
} |
并且file test是
1
| test: ELF 32-bit LSB executable, ARM, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.31, BuildID[sha1]=0xf2e49db65394b77c77ee5b65b83c0cc9220cbfc0, not stripped |
-
如果在没有操作系统的情况下运行,则printf是您要做的最后一件事,当然不是您要为该系统编写的第一个程序。 打开一个在qemu上没有意义的LED,但是将字符从串行端口/ uart塞到串行终端通常是不重要的。 另外,您还想从不是C的汇编程序开始,因为引导代码也不是一件容易的事,因为您必须确保了解内存映射,程序的加载位置等。
-
这是由于没有将arm库安装为系统库(即使它们已作为交叉编译器的目标库安装)。 如果发行版支持它,则可以将arm安装为多体系结构目标(例如同时支持x86和x86_64的方式)。 在Ubuntu中,多数民众赞成在apt-add-architecture arm && apt-get install libc6:arm之类。 我不知道薄荷。 如果您不想考虑,只需使用-static进行编译。
您可以通过使用-L标志提供arm-linux-gnueabi共享库的路径来运行示例。
1
| qemu-arm -L /usr/arm-linux-gnueabi/ |
还请确保未设置LD_LIBRARY_PATH。
-
Ubuntu 16.04软件包gcc-arm-linux-gnueabihf的-L usrarm-linux-gnueabihf。
-
适用于ARMv8 64的qemu-aarch64 -L / usr / aarch64-linux-gnu /
1
| $ export QEMU_LD_PREFIX=/usr/arm-linux-gnueabi |
这对我有用。
基本上与以下内容相同:
1
| $ qemu-arm -L /usr/arm-linux-gnueabi/ |
您可以将其添加到?/ .bashrc文件中,这样就不必在每次打开终端时都键入它。
使用汇编代码运行C程序时,我也遇到了这个问题。我的解决方案是使用例如" -static"选项构建可执行文件
1
| arm-linux-gnueabi-gcc -static -g main.c square.s |
然后
将不会报告错误消息"找不到/lib/ld-linux.so.3"。
唯一的缺点是可执行文件可能很大。但是,当您只想测试代码时,这很有用。
当然,您可以使用Balau中的方法(请参阅artless noise的答案)。但是,如果您不想在此步骤中被" UART串行端口"之类的东西感到沮丧,而这仅仅是运行一个简单的"测试"功能,请尝试一下我的解决方法。
-
杜德!它的2018年和您的解决方案为我工作想要详细说明-static如何像魅力一样工作吗?
-
@ J.Doe偶然发现了这个,所以我认为我应该详细说明。我已经使用-static标志编译了一段时间了。之所以起作用,是因为使用此标志进行交叉编译时,所有依赖项都将编译为可执行文件本身,而不是留给链接程序解析。在另一台计算机(在本例中为qemu-arm)上运行生成的可执行文件时,没有未解决的依赖关系,因此它就像一个超级按钮一样工作。
-
@agdhruv,它的2019年,我在很长一段时间后重新登录到该帐户。您的答案只有3天了。 =))
我通过将以下库复制到/ lib来解决了该问题,但我相信应该有比我发明的这种讨厌的解决方案更好的解决方案!
1 2 3
| sudo cp /usr/arm-linux-gnueabi/lib/ld-linux.so.3 /lib
sudo cp /usr/arm-linux-gnueabi/lib/libgcc_s.so.1 /lib
sudo cp /usr/arm-linux-gnueabi/lib/libc.so.6 /lib |
如果我有兴趣知道,请告诉我是否还有其他更好的解决方案。
-
是的,当然可以,但是在这种情况下,您需要运行Linux。最初的问题是要避免使用Linux。您没有复制库并在没有Linux内核的情况下运行qemu虚拟机吗?这似乎是不可能的。
-
我发现qemu-arm的-L / usr / arm-linux-gnueabihf /选项可以正常工作,如上所述。
-
@artlessnoise,这里没有错。这个答案使库对qemu可见,因此模拟二进制文件将链接。它不引导仿真的Linux系统。它仍在使用syscall仿真。
-
@artlessnoise,那就是qemu所做的]。首先,它必须能够将ARM二进制文件与ARM库链接(除非它是静态的),然后这些库进行系统调用,而qemu捕获这些系统调用并转换为主机OS。它比必须模拟整个ARM Linux内核要有效得多。该解决方案只是将库移动到qemu可以找到它们的地方。这些库仍然必须进行系统调用才能发生任何有趣的事情。
-
@ sh1对,但是ARM syscall接口与x86不同。有些事情不存在,而另一件事却存在。 qemu必须执行此翻译或在某些情况下执行它;这可能是不可能的,因为它需要直接访问Linux内部。使用无臂编译器似乎没有太多问题。同样,这取决于您要实现的目标。我没有说这在所有情况下都行不通。但是,它需要权衡其他解决方案。
如果要在没有Linux的情况下运行ARM,则至少需要一个不同的编译器。 arm-linux-gnueabi-gcc是Linux的编译器。编译器和libc紧密链接。您将需要一个带有可移植层的newlib编译器用于qemu.porting newlib
请参阅:Balau和Google newlib + qemu。 newlib端口托管在Github上,看起来与Balau博客相同。
通常,非Linux gcc称为arm-none-eabi-gcc。一些配置脚本可以识别前缀arm-none-eabi-。
-
如果您想进行系统调用很重要,那么对于不需要系统调用的裸机工作,您可以在大多数情况下使用工具链的arm-linux-gnueabi或arm-none-eabi风格。
-
github.com/dwelch67/yagbat有一个qemu目录,我正在开发一个单独的qemu裸机示例存储库,但尚无任何发布。
-
@dwelch对,您也可以使用-nostdlib进行编译,但是随后您必须编写自己的库和libgcc东西。例如,当您除以零时,Linux版本的libgcc与newlib会有不同(我认为它将重置)。我认为使用newlib gcc可以更好地使用此海报,但是如果您小心一点,可以使用arm-linux-gnueabi-gcc编译器,这是正确的。此路由可能会出现很多随机链接程序/加载程序错误,这些错误通常不容易找出。
-
答案的关键是" qemu的可移植性层",这很重要。如果您进行系统调用,则任何旧的arm-none-eabi都不起作用。但是,如果您不进行系统调用,那么任何arm-linux-gnueabi或arm-none-eabi都可以作为编译器工作,并加强使用-nostdlib等...如果您可以构建自己的数据库或为它找到新库然后,该平台绝对可以使用无臂eabi。
对我有用的一个变体是直接传递加载程序库,并使用加载程序参数--library-path指定所需的库路径。例如:
1 2
| $ TOOLCHAIN_ROOT=/usr/local/gcc-linaro-arm-linux-gnueabihf-4.7-2013.03-20130313_linux/arm-linux-gnueabihf
$ qemu-arm $TOOLCHAIN_ROOT/libc/lib/ld-linux-armhf.so.3 --library-path $TOOLCHAIN_ROOT/libc/lib/arm-linux-gnueabihf:/$TOOLCHAIN_ROOT/lib ./my_executable |
或者等效地导出LD_LIBRARY_PATH而不是使用--library-path。