尝试 运行 目标设备上的交叉编译可执行文件失败并显示:没有这样的文件或目录

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

我陷入了不太阳光的交叉编译世界。

我正在尝试为我的 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,但从那以后我就无法像现在这样再次恢复该错误 returns No such file or directory。我猜那个特定的尝试只是一个糟糕的 t运行sfer 之类的。

由于评论中没有人发布答案,我想我很高兴 ;)

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

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

objdump -j .interp -s ./hello_world

在此示例中,可执行文件的 .interp 字段是 /lib/ld-linux.so.3,但 BeagleBone Black 上的动态 linker 的名称是 /lib/ld-linux-armhf.so.3

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

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

只需添加符号 link 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 充满活力 linker /lib/ld-linux.so.3.

我在 BBB 上创建了一个符号 link:

ln -s /lib/ld-linux.so.3 /lib-linux-armhf.so.3

现在交叉编译的应用程序可以在 BBB 上运行。 BBB 是 运行 原始的 Angstrom 分布。

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

我假设错误消息是由于找不到动态 linker 文件,而不是应用程序不存在。

如何识别问题?

file cross_compiled_executable

包含如下内容:

interpreter /lib/ld-uClibc.so.0

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

如何解决问题?

使用合适的编译器,或者:

  • 创建磁盘映像的人必须为您提供交叉编译器或告诉您如何构建它,例如crosstool-ng. For BeagleBone asked at:
  • 编译你自己的图像和交叉编译器,例如Buildroot. Here is a generic QEMU example. Buildroot has BeagleBone support.
  • 在目标上使用本机编译器。但通常目标比您的主机慢得多,并且 space 受到限制,因此您可能不想这样做。

    您也许还可以使用 QEMU 等功能性仿真器来构建,然后仅 运行 在较慢的平台上构建程序,例如gem5或者慢板。

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