如何解决;加载共享库时出错“;尝试使用qemu arm运行arm二进制文件时?

如何解决;加载共享库时出错“;尝试使用qemu arm运行arm二进制文件时?,arm,qemu,Arm,Qemu,我正在运行LinuxMint14,安装了qemu、qemu用户和gnueabi工具链。我使用arm linux gnueabi gcc test.c-o test编译了test.c 当我尝试运行qemu-arm/usr/arm-linux-gnueabi/lib/ld-linux.so.3测试时 我收到一个错误,提示:test:error,加载共享库时出错:test:无法打开共享对象文件:没有这样的文件或目录。运行qemu-arm-test,正如我之前尝试过的那样,给出了/lib/ld-linu

我正在运行LinuxMint14,安装了qemu、qemu用户和gnueabi工具链。我使用
arm linux gnueabi gcc test.c-o test编译了test.c

当我尝试运行
qemu-arm/usr/arm-linux-gnueabi/lib/ld-linux.so.3测试时

我收到一个错误,提示:
test:error,加载共享库时出错:test:无法打开共享对象文件:没有这样的文件或目录
。运行
qemu-arm-test
,正如我之前尝试过的那样,给出了
/lib/ld-linux.so.3:没有这样的文件或目录

但是,该文件确实存在并且可以访问

$ 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内核吗

测试c是

#include <stdio.h>
int main() {
    printf("this had better work\n");
}

如果你想在没有Linux的情况下运行ARM,那么你需要一个不同的编译器(至少)
arm linux gnueabi gcc
是一个针对linux的编译器。编译器和
libc
紧密相连。您需要一个带有qemu可移植层的
newlib
编译器

见:和。一个
newlib
端口位于,看起来与Balau博客相同


通常,非Linux gcc称为
arm none eabi gcc
。前缀arm none eabi-被一些配置脚本识别。

我通过将以下库复制到/lib中解决了这个问题,但我相信应该有更好的解决方案,而不是我发明的这个讨厌的解决方案

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

请告诉我是否还有其他更好的解决方案,我很想知道。

您可以通过使用-L标志提供arm linux gnueabi共享libs的路径来运行该示例

qemu-arm -L /usr/arm-linux-gnueabi/
另外,请确保未设置LD_LIBRARY_路径

unset LD_LIBRARY_PATH

我在用汇编代码运行C程序时也遇到了这个问题。例如,我的解决方案是使用选项“-static”构建可执行文件

arm-linux-gnueabi-gcc -static -g main.c square.s
然后

不会报告“找不到/lib/ld linux.so.3”错误

唯一的缺点是可执行文件的大小可能很大。但当您只想测试代码时,它会很有帮助

当然,您可以使用Balau的方法(参见artless noise的答案)。但是,如果您不想在这一步中对诸如“UART串行端口”之类的东西感到沮丧,这只是为了运行一个简单的“测试”功能,请尝试一下我的修复程序

$ export QEMU_LD_PREFIX=/usr/arm-linux-gnueabi
这对我有用。 这基本上与:

$ qemu-arm -L /usr/arm-linux-gnueabi/

您可以将它添加到~/.bashrc文件中,这样您就不必每次打开终端时都键入它。

一个对我有效的变体是直接传递加载程序库,并使用加载程序参数
--library path
指定所需的库路径。例如:

$ 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

如果您想进行系统调用,那么对于不需要系统调用的裸机工作,您可以在大多数情况下使用arm linux gnueabi或arm none eabi风格的toolchain。有一个qemu目录,我正在编写一个单独的qemu裸机示例repo,但还没有任何东西要发布。@dwelch Right,您也可以使用
-nostlib
编译,但是您必须编写自己的库和
libgcc
之类的东西。例如,当您除以零时,
libgcc
的Linux版本执行与
newlib
不同的操作(我认为这会重置)。我认为这张海报最好使用一个新的lib gcc,但是你是对的,如果你小心的话,你可以使用
armlinux-gnueabi-gcc
编译器。这条路线可能会出现很多随机的链接器/加载程序错误,这些错误通常不容易弄清楚。答案的关键是“qemu的可移植层”,这是一个大问题。如果您进行系统调用,任何旧的arm-one-eabi都将无法工作。但是如果你不进行系统调用,那么任何arm-linux gnueabi或arm-none-eabi都将作为编译器工作,并且为了强调你使用-nostlib等。如果你可以为平台构建自己的库或找到新库,那么一定要使用arm-none-eabi。如果在没有操作系统的情况下运行,printf是你最不想做的事情,当然不是你想为这个系统写的第一个程序。打开一个在qemu上没有意义的led,但是将一个字符从串行端口/uart干扰到串行终端通常是很简单的事情。此外,您可能希望从汇编程序开始,而不是从C开始,因为引导代码也很重要,因为您必须确保了解内存映射、程序加载的位置等。这是由于arm库不是作为系统库安装的(即使它们是作为交叉编译器的目标库安装的)。如果发行版支持它,那么您可以将arm安装为多功能目标(比如同时支持x86和x86_64)。在Ubuntu中,这类似于
apt-addarchitecture-arm&&apt-get-install-libc6:arm
。我不知道薄荷糖。如果不想考虑的话,只需使用
-static
编译即可。是的,当然可以,但在这种情况下,您需要运行Linux。最初的问题是想避开Linux。您没有复制库并运行没有Linux内核的qemu虚拟机吗?这似乎是不可能的。我发现qemu arm的-L/usr/arm-linux-gnueabihf/选项可以工作,正如上面所建议的…@artlessnoise,这里没有什么问题。这个答案使库对qemu可见,因此模拟的二进制文件将链接。它不是在启动一个模拟的Linux系统。它仍在使用系统调用模拟。@artlessnoise,这就是qemu所做的。首先,它必须能够将ARM二进制文件链接到ARM库(除非是静态的),然后这些库进行系统调用,qemu捕获这些系统调用,然后将其转换到主机操作系统。它比模拟整个ARM Linux内核要高效得多。此解决方案只是将库移动到
$ qemu-arm -L /usr/arm-linux-gnueabi/
$ 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