本文介绍了尝试在目标设备上运行交叉编译的可执行文件失败:没有这样的文件或目录的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

我正在尝试为我的 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.oarm-linux-gnueabi-gcc bin/obj/main.o -o bin/hello_world

我通过 SCP 将文件传输到 BeagleBone,并使用 chmod +x hello_world

设置可执行权限

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

-bash: ./hello_world: 没有那个文件或目录

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

$ 文件 hello_worldhello_world:ELF 32 位 LSB 可执行文件,ARM,版本 1 (SYSV),动态链接(使用共享库),用于 GNU/Linux 2.6.32,BuildID[sha1]=0x24b659b7a41fe043a6f4649d4ebfb5e692ebf0c7,未剥离$ 文件/sbin/init/sbin/init:ELF 32 位 LSB 可执行文件,ARM,版本 1 (SYSV),动态链接(使用共享库),用于 GNU/Linux 2.6.26,BuildID[sha1]=0xd21f6957ec031a27d567b3d5e6aa14b9e0c30c3

ldd 的结果是:

$ ldd hello_world不是动态可执行文件

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

arm-linux-gnueabi-gcc -c -O0 -g3 -Wall -march=armv7-a -mtune=cortex-a8 main.c -o bin/obj/main.oarm-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 使用特定的浮点寄存器和硬浮点版本(armhf)的 EABI,但原始 EABI(armel)code>) 使用整数寄存器来传递浮点数.结果,armel 程序将在 armhf 上运行(前提是动态链接器设置为正确的路径!),但反之则不然.

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

I've got caught in the not-so-sunny world of cross-compilation.

I'm trying to compile a simple hello world application for my BeagleBone Black (which runs a TI Cortex-A8 processor).

First of all, I compiled and ran successfully the hello world application on x86 with gcc

Then I changed my compilation settings to the following:

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

I transferred the file via SCP to the BeagleBone, and set executable permissions with chmod +x hello_world

Upon running it (./hello_world), my only response is:

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

The output of file matches that of /sbin/init as I would expect:

$ 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

The result of ldd is:

$ ldd hello_world
    not a dynamic executable

I tried adding a suitable platform and CPU type, changing my compilation to:

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

This initially started giving me a new error: Text file busy, but I have since been unable to get that error back again as it now returns No such file or directory. I'm guessing that particular attempt was just a bad transfer or something.

解决方案

Since nobody from the comments posted the answer, I guess I get the pleasure ;)

No such file or directory comes from when the kernel tries to invoke the dynamic linker specified by the ELF executable's .interp field, but no such file exists.

The .interp field can be found with the following command:

objdump -j .interp -s ./hello_world

In the case of this example, the executable's .interp field was /lib/ld-linux.so.3, but the name of the dynamic linker on the BeagleBone Black is /lib/ld-linux-armhf.so.3.

This happened because the program was compiled with a slightly different toolchain to the one required for the platform. It should be arm-linux-gnueabihf-* rather than arm-linux-gnueabi-*.

The difference between the two is that the Cortex-A8 uses specific floating point registers with the hard-float version (armhf) of the EABI, but the original EABI (armel) uses integer registers for passing around floating point numbers. As a result, armel programs will run on armhf (provided the dynamic linker is set to the correct path!), but not vice versa.

Simply adding a symbolic link ln -s /lib/ld-linux-armhf.so.3 /lib/ld-linux.so.3 is enough to resolve this issue, but the correct fix is to use the right toolchain when compiling the program in the first place.

这篇关于尝试在目标设备上运行交叉编译的可执行文件失败:没有这样的文件或目录的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

07-29 20:24