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

CJx*_*JxD 10 c c++ arm cross-compiling beagleboneblack

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

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

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

然后我将编译设置更改为以下内容:

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
Run Code Online (Sandbox Code Playgroud)

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

在运行它(./hello_world)时,我唯一的回答是:

-bash: ./hello_world: No such file or directory
Run Code Online (Sandbox Code Playgroud)

正如我所期望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
Run Code Online (Sandbox Code Playgroud)

结果ldd是:

$ ldd hello_world
    not a dynamic executable
Run Code Online (Sandbox Code Playgroud)

我尝试添加合适的平台和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
Run Code Online (Sandbox Code Playgroud)

这最初开始给我一个新的错误:Text file busy但是我已经无法再次收到该错误,因为它现在返回No such file or directory.我猜这个特定的尝试只是一个糟糕的转移或其他东西.

CJx*_*JxD 18

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

No such file or directory来自内核尝试调用ELF可执行文件.interp字段指定的动态链接器,但不存在此类文件.

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

objdump -j .interp -s ./hello_world
Run Code Online (Sandbox Code Playgroud)

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

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

两者之间的区别在于Cortex-A8使用特定的浮点寄存器和armhfEABI 的hard-float版本(),但原始的EABI(armel)使用整数寄存器来传递浮点数.因此,armel程序将运行armhf(假设动态链接器设置为正确的路径!),但反之亦然.

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

  • 在Cortex-A8之前很久就有ARM硬件浮点.不同之处在于原始ARM EABI指定浮点值是在整数寄存器中的函数之间传递的,而不是在硬件浮点寄存器中传递,以允许在没有浮点的硬件上使用相同的ABI.编译器仍会发出硬件指向点代码.gnueabihf使用浮点寄存器. (3认同)