尝试在目标设备上运行交叉编译的可执行文件失败:没有这样的文件或目录
我陷入了不那么阳光明媚的交叉编译世界。
我正在尝试为我的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
。 我猜这个特定的尝试只是一个糟糕的转移或其他东西。
由于评论中没有人发布答案,我想我很高兴;)
当内核尝试调用ELF可执行文件的.interp
字段指定的动态链接器时, No such file or directory
,但不存在此类文件。
可以使用以下命令找到.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在ARMv7中使用基于硬件的浮点运算,但以前版本的ARM指令集使用了基于软件的技术。 这是armhf
和armhf
之间的区别。 因此, armhf
程序将在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上运行该程序给出了错误:“没有这样的文件或目录”
使用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询问: 工具链为BBB交叉编译应用程序
- 编译自己的图像和交叉编译器,例如使用Buildroot 。 这是一个通用的QEMU示例 。 Buildroot 拥有BeagleBone支持 。
-
在目标上使用本机编译器。 但通常目标比主机慢得多,而且空间有限,所以你可能不想这样做。
您也可以使用function仿真器(如QEMU)进行构建,然后仅在较慢的平台上运行程序,例如gem5或慢速板。
只是破解interpreter
器可能是不够的,特别是你必须确保程序和目标libc之间的二进制兼容性,或程序和内核接口(系统调用, /proc
等),如果你尝试使用-static
(目标内核)可能太旧了,不包含所需的接口)。 唯一可靠的解决方案是使用正确的工具链。