试图在目标设备上运行一个交叉编译的可执行文件失败,出现以下错误:

Trying to run a cross-compiled executable on target device fails with: No such file or directory

本文关键字:失败 可执行文件 交叉编译 错误 一个 目标 运行      更新时间:2023-10-16

我陷入了交叉编译这个不那么阳光的世界。

我正试图为我的BeagleBone Black(运行TI Cortex-A8处理器)编译一个简单的hello world应用程序。

首先,我用gcc在x86上编译并成功运行了hello world应用程序

然后我将编译设置更改为:

arm-linux-gnueabi-gcc -c -O0 -g3 -Wall main.c -o bin/obj/main.o
arm-linux-gnueabi-gcc bin/obj/main.o -o bin/hello_world

我通过SCP将文件传输到BeagleBone,并使用chmod +x hello_world设置可执行权限

运行后(./hello_world),我唯一的反应是:

-bash: ./hello_world: No such file or directory

file的输出与/sbin/init的输出相匹配,正如我所期望的那样:

$ file hello_world
hello_world: ELF 32-bit LSB executable, ARM, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.32, BuildID[sha1]=0x24b659b7a41fe043a6f4649d4ebfb5e692ebf0c7, not stripped
$ file /sbin/init
/sbin/init: ELF 32-bit LSB executable, ARM, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.26, BuildID[sha1]=0xd21f6957ec031a27d567b3d5e6aa14b9e0c30c37, stripped

ldd的结果是:

$ ldd hello_world
    not a dynamic executable

我尝试添加合适的平台和CPU类型,将我的编译更改为:

arm-linux-gnueabi-gcc -c -O0 -g3 -Wall -march=armv7-a -mtune=cortex-a8  main.c -o bin/obj/main.o
arm-linux-gnueabi-gcc bin/obj/main.o -o bin/hello_world

这最初开始给我一个新的错误:Text file busy,但我已经无法得到这个错误回来了,因为它现在返回No such file or directory

既然评论中没有人发表答案,我想我得到了乐趣;)

No such file or directory来自内核试图调用由ELF可执行文件的.interp字段指定的动态链接器,但是不存在这样的文件。

.interp字段可以用下面的命令找到:

objdump -j .interp -s ./hello_world

在这个例子中,可执行文件的.interp字段是/lib/ld-linux.so.3,但是BeagleBone Black上的动态链接器的名称是/lib/ld-linux-armhf.so.3

发生这种情况是因为程序是用与平台所需的工具链略有不同的工具链编译的。应该是arm-linux-gnueabihf-*而不是arm-linux-gnueabi-*

两者之间的区别在于Cortex-A8在硬浮点版本的EABI (armhf)中使用特定的浮点寄存器,而原始的EABI (armel)使用整数寄存器来传递浮点数。因此,armel程序将在armhf上运行(前提是动态链接器被设置为正确的路径!),但反之亦然。

简单地添加一个符号链接ln -s /lib/ld-linux-armhf.so.3 /lib/ld-linux.so.3就足以解决这个问题,但正确的解决方法是在编译程序时首先使用正确的工具链

我也遇到了同样的问题。我使用apt-get从Ubuntu存储库下载并安装了gcc-arm-linuc-gnueabihf包到我的Ubuntu PC上。然后我编译了一个helloworld测试程序,并使用sftp将其下载到我的BeagleBone上。

尝试在BBB上运行程序给出错误:"No such file or directory"

使用objdump我发现ELF可执行文件中的.interp字段是/lib/ld_linux_armhf.so.3。我的BBB有动态链接器/lib/ld-linux.so.3

我在BBB创建了一个符号链接:

ln -s /lib/ld-linux.so.3 /lib-linux-armhf.so.3
现在交叉编译的应用程序可以在BBB上工作了。BBB运行的是原来的Angstrom发行版。

这不是理想的修复。现在我需要在Ubuntu中配置工具链来为应用程序添加正确的动态链接器名称,或者更新BBB以在工具链中指定一个动态链接器。

我认为错误消息是由于没有找到动态链接器文件,而不是应用程序不存在。

如何识别问题?

file cross_compiled_executable

包含如下内容:

interpreter /lib/ld-uClibc.so.0

,问题是该文件在目标文件中不存在。

如何解决这个问题?

使用合适的编译器:

  • 创建磁盘映像的人必须向您提供交叉编译器或确切地告诉您如何构建它,例如使用crosstool-ng。对于BeagleBone在:Toolchain上询问的关于交叉编译BBB应用程序的问题
  • 编译你自己的镜像和交叉编译器,例如使用builroot。下面是一个通用的QEMU示例。Buildroot支持BeagleBone。
  • 在目标上使用本机编译器。但是通常目标比您的主机慢得多,而且空间有限,所以您可能不希望这样做。

    您也可以使用功能模拟器,如QEMU来构建,然后只在较慢的平台上运行程序,例如gem5或慢板。

仅仅破解interpreter可能是不够的,特别是如果您尝试使用-static(目标内核可能太旧,不包含所需的接口),您必须确保程序和目标libc之间的二进制兼容性,或者程序和内核接口(系统调用,/proc等)之间的二进制兼容性。唯一可靠的解决方案是使用正确的工具链。

相关文章: