交叉编译时为 32 位 armhf 设置了错误的运行时 linker/interpreter

Wrong runtime linker/interpreter set for 32-bit armhf when cross-compiling

我正在利用 yocto (dunfell) 为多个不同的体系结构交叉编译一个项目。具体来说,我的目标是 64 位 RaspberryPi4 (aarch64) 和 32 位 Orange Pi (armhf)。我正在交叉编译的项目在为 raspi 目标构建时编译和 运行s 没有问题; 运行时间链接器设置正确,运行 没有问题。然而,每当我为 Orange Pi 目标构建程序时,程序似乎编译没有问题,但当我尝试在平台上执行它时,我收到“找不到文件”错误。

这似乎是因为解释器(运行时间链接器)被设置为 /usr/lib/ld.so,它实际上并不在系统上。见下文:

$ file my-exec
my-exec: ELF 32-bit LSB executable, ARM, EABI5 version 1 (SYSV), dynamically linked, interpreter /usr/lib/ld.so.1, with debug_info, not stripped

相比之下,当我为 raspi 目标构建相同的程序时,似乎为系统正确设置了解释器:

$ file my-exec
my-exec: ELF 64-bit LSB executable, ARM aarch64, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux-aarch64.so.1, with debug_info, not stripped

这个问题似乎只针对 Orange Pi 目标上的这个项目。相比之下,Orange Pi 目标上的其他项目如下所示并且 运行 没有问题:

$ file other-exec
other-exec: ELF 32-bit LSB shared object, ARM, EABI5 version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux-armhf.so.3, for GNU/Linux 3.2.0, stripped

我想了解的是以下内容:

  1. 哪些因素可能会影响编译时选择的解释器?我已经对此进行了一些深入研究,但我的 Makefile 中没有明确设置任何可能导致此问题的内容。此外,当我构建一个简单的 hello world 应用程序时,会选择正确的解释器。这似乎是我的 compiling/linking 中的一组标志导致的。下面是 compiling/linking 输出(我已经排除了它正在构建的所有使用相同参数的库):
NOTE: make -j 24 i2c-core VERBOSE=1 CC=arm-poky-linux-gnueabi-gcc  -march=armv7ve -mthumb -mfpu=neon -mfloat-abi=hard -fstack-protector-strong  -D_FORTIFY_SOURCE=2 -Wformat -Wformat-security -Werror=format-security --sysroot=/home/my-yocto-os/build/tmp/work/armv7vet2hf-neon-poky-linux-gnueabi/my-exec/1.0+git999-r0/recipe-sysroot LD=arm-poky-linux-gnueabi-ld --sysroot=/home/my-yocto-os/build/tmp/work/armv7vet2hf-neon-poky-linux-gnueabi/my-exec/1.0+git999-r0/recipe-sysroot 

arm-poky-linux-gnueabi-gcc  -march=armv7ve -mthumb -mfpu=neon -mfloat-abi=hard -fstack-protector-strong  -D_FORTIFY_SOURCE=2 -Wformat -Wformat-security -Werror=format-security --sysroot=/home/my-yocto-os/build/tmp/work/armv7vet2hf-neon-poky-linux-gnueabi/my-exec/1.0+git999-r0/recipe-sysroot -I.. -I. -g -std=gnu99 -Wall -Wextra -pedantic -Wshadow -Wpointer-arith -Wcast-align -Wwrite-strings -Wmissing-prototypes -Wmissing-declarations -Wredundant-decls -Wnested-externs -Winline -Wno-long-long -Wconversion -Wstrict-prototypes -DBUILD_CORE -c -o build/other.o ../other.c


...


arm-poky-linux-gnueabi-ld --sysroot=/home/my-yocto-os/build/tmp/work/armv7vet2hf-neon-poky-linux-gnueabi/my-exec/1.0+git999-r0/recipe-sysroot  build/my-exec.o build/other.o build/other1.o -luv -lsystemd -lc --entry main -o build/exe/my-exec


  1. 正在设置的链接器 (/usr/lib/ld.so.1) 似乎是一个非常常用的链接器,那么为什么它实际上没有出现在我的系统上?
  2. 我是否从根本上误解了导致这种结果的 ARM 架构?我可以在链接时设置不同的标志来解决这个问题吗?

我还有一条可能相关也可能不相关的信息如下: 我在构建 Raspi 目标时遇到的一个问题(实际上出现在两个目标上)是编译器无法找到入口符号。这是一个相当成熟的项目,历史上已经使用交叉编译器对其进行编译,但采用的方式与 yocto 不同。这在过去从来都不是问题。直到我将 --entry main 添加到链接器标志中,这个问题才得到解决。我想知道是否有更根本的问题导致了这些奇怪的结果。

感谢您对此提供的任何帮助。如果您对我的环境有任何其他问题,请告诉我。

调试了几天,发现问题所在。如果任何人在链接方面的知识比我多,想插话添加一些东西,请做。最终,通过使用 gcc 作为链接器解决了这个问题,而不是使用 ld(由 yocto 的交叉编译器提供的;即 aarch64-poky-linux-gcc)。

为了做到这一点,我修改了我的食谱以将 LD=${CC} LDFLAGS=${LDFLAGS} 传递到我的 Makefile。现在,它可以针对 RPi 和 OrangePi 目标正确构建和执行。

我相信主要是因为yocto提供的LDFLAGS其实是ld无法解析的。根据我的研究,ld 似乎通常由 gcc 调用。然而,这些标志仍然需要到达编译器。因此,最初,需要传递给链接的 LDFLAGS 根本没有被传递,因为我只是假设这样做会出错。因此,请确保您将 yocto 给您的 LDFLAGS 传递给 gcc.