ARM编译错误,可执行文件使用的VFP寄存器,而不是目标文件

Posted

技术标签:

【中文标题】ARM编译错误,可执行文件使用的VFP寄存器,而不是目标文件【英文标题】:ARM compilation error, VFP registers used by executable, not object file 【发布时间】:2012-04-02 23:15:28 【问题描述】:

过去几天我一直遇到这个问题,我无法理解这里到底发生了什么,或者问题是什么。

我有一个带有这些标志的生成文件:

CC = arm-linux-gnueabihf-gcc-4.6
FLAGS = -O3 -march=armv7-a -mtune=cortex-a9 -mfpu=neon -ftree-vectorize -mfloat-abi=softfp -std=gnu99

我在 .a 文件中有一个库,其中包含一些目标文件,我需要做的就是将它们与我的可执行文件链接起来。我知道原型和所有这些,唯一抱怨的是:

/usr/bin/ld: error: *EXECUTABLE* uses VFP register arguments, *OBJECTFILE* does not
/usr/bin/ld: failed to merge target specific data of file *OBJECTFILE*

当我不使用 -mfloat-abi=softfp 时,我收到另一个与浮点寄存器有关的错误。

有没有人知道是什么原因造成的,以及我可以做些什么来解决这个问题,例如让我的可执行文件不使用虚拟浮点寄存器参数?

x@x:~/Desktop/perf_test$ make
arm-linux-gnueabihf-gcc-4.6 -c -O3 -march=armv7-a -mtune=cortex-a9 -mfpu=neon -ftree-vectorize -std=gnu99 -mfloat-abi=softfp  perf_test.c ../baseline/util.c
arm-linux-gnueabihf-gcc-4.6 -o perf_test perf_test.o util.o  ../baseline/lib.a
/usr/bin/ld: error: perf_test uses VFP register arguments, perf_test.o does not
/usr/bin/ld: failed to merge target specific data of file perf_test.o
/usr/bin/ld: error: perf_test uses VFP register arguments, util.o does not
/usr/bin/ld: failed to merge target specific data of file util.o
/usr/bin/ld: error: perf_test uses VFP register arguments, ../baseline/lib.a(a.o) does not
/usr/bin/ld: failed to merge target specific data of file ../baseline/lib.a(a.o)
/usr/bin/ld: error: perf_test uses VFP register arguments, ../baseline/lib.a(b.o) does not
/usr/bin/ld: failed to merge target specific data of file ../baseline/lib.a(b.o)
/usr/bin/ld: error: perf_test uses VFP register arguments, ../baseline/lib.a(c.o) does not
/usr/bin/ld: failed to merge target specific data of file ../baseline/lib.a(c.o)
/usr/bin/ld: error: perf_test uses VFP register arguments, ../baseline/lib.a(d.o) does not
/usr/bin/ld: failed to merge target specific data of file ../baseline/lib.a(d.o)
/usr/bin/ld: error: perf_test uses VFP register arguments, ../baseline/lib.a(e.o) does not
/usr/bin/ld: failed to merge target specific data of file ../baseline/lib.a(e.o)
/usr/bin/ld: error: perf_test uses VFP register arguments, ../baseline/lib.a(f.o) does not
/usr/bin/ld: failed to merge target specific data of file ../baseline/lib.a(f.o)
collect2: ld returned 1 exit status
make: *** [perf_test] Error 1

【问题讨论】:

【参考方案1】:

这是猜测,但您可能还需要为链接阶段提供部分或全部浮点相关开关。

【讨论】:

【参考方案2】:

您的目标三元组表明您的编译器已针对 hard-float ABI 进行了配置。这意味着 libgcc 库也将是 hardfp。该错误消息表明您的系统至少有一部分正在使用 soft-float ABI。

如果编译器启用了 multilib(你可以用 -print-multi-lib 告诉你),那么你可以使用 -mfloat-abi=softfp,但如果没有,那么这个选项对你没有多大帮助:gcc 会很高兴地生成 softfp 代码,但是有'将没有兼容的 libgcc 链接。

基本上,hardfp 和 softfp 只是不兼容。您需要以一种或另一种方式配置整个系统。

编辑:一些发行版是或将是“多架构”。如果您有其中之一,则可以同时安装两个 ABI,但这是通过将所有内容加倍来完成的——兼容性问题仍然存在。

【讨论】:

当我使用 -hard 编译时,它会删除我编写的可执行文件和代码,但库仍然出错。我的问题基本上是假装我什么都不知道。这里发生了什么,为什么? 您的库和/或可执行文件不兼容,因为它们使用不同的过程调用约定:一个在 VFP 寄存器中传递浮点值,另一个在核心寄存器中传递它们。 这个修复对我有用。但是,请确保将-mfloat-abi=softfp标志添加到编译器和链接器中,否则错误将持续存在【参考方案3】:

也可以通过添加几个标志来解决该错误,例如-marm -mthumb-interwork。避免同样的错误对我很有帮助。

【讨论】:

【参考方案4】:

我发现在 glibc binutils 和 gcc 交叉编译的 arm hardfloat 系统上,使用 gcc 会出现相同的错误。

通过将-mfloat-abi=hard导出到flags来解决,然后gcc编译没有错误。

【讨论】:

【参考方案5】:

也使用相同的编译器选项进行链接。

例子:

gcc  -mfloat-abi=hard fpu=neon -c -o test.cpp test.o
gcc  -mfloat-abi=hard fpu=neon -c test1.cpp test1.o
gcc test.o test1.o mfloat-abi=hard fpu=neon HardTest

【讨论】:

我有相同的 mfloat-abi 选项,但错过了链接器的 mcpu。这导致了 VFP 错误。【参考方案6】:

就我而言,CFLAGS = -O0 -g -Wall -I. -mcpu=cortex-m4 -mthumb -mfpu=fpv4-sp-d16 -mfloat-abi=soft 提供了帮助。如您所见,我将它用于我的 stm32f407。

【讨论】:

【参考方案7】:

在我的特殊情况下,-g -march=armv7-a -mfloat-abi=hard -mfpu=neon -marm -mthumb-interwork 有效。

【讨论】:

【参考方案8】:

我在 STM32F4 上使用 Atollic for ARM 时遇到了这个问题(我猜它适用于所有带 FPU 的 STM32)。

使用 SW 浮点对我来说效果不佳(因此编译正确)。

当 STM32cubeMX 为 TrueStudio (Atollic) 生成代码时,它不会在 C/C++ 构建设置中设置 FPU 单元(不确定为其他 IDE 生成的代码)。

"Target" 中为(在项目属性构建设置下)设置 FPU:

汇编器 C 编译器 C 链接器

然后您可以选择混合硬件/软件 fp 或使用硬件。

为预期目标添加生成的命令行:

-mfloat-abi=hard -mfpu=fpv4-sp-d16

armatollic

【讨论】:

【参考方案9】:

这个答案表面上可能看起来不相关,但这个错误信息有一个间接原因。

首先,“使​​用 VFP 寄存器...”错误消息是由在您的构建中混合使用 mfloat-abi=soft 和 mfloat-abi=hard 选项直接引起的。对于要链接的所有对象,此设置必须一致。这个问题的其他答案很好地涵盖了这一事实。

此错误的间接原因可能是由于 Eclipse 编辑器被项目的“.cproject”文件中的自我造成的错误弄糊涂了。 Eclipse 编辑器经常重新调整文件链接,有时它会在您更改目录结构或文件位置时自行中断。这也可能会影响 gcc 编译器的路径设置 - 并且仅适用于项目文件的子集。虽然我还不确定导致此故障的确切原因,但用备份副本替换 .cproject 文件为我解决了这个问题。就我而言,我在添加包含目录路径后注意到 .java.null.pointer 错误并开始突然收到“VFP 注册错误”消息。在构建日志中,我注意到 gcc 编译器的不同路径被用于工作区本地的一些源,但不是全部!?由于未知原因,两个 gcc 编译器使用不同的浮点设置 - 因此出现 VFP 寄存器错误。

我将 .cproject 设置与旧副本进行了比较,并观察到导致问题的源条目的差异 - 即使项目设置的覆盖被禁用。通过用旧版本替换 .cproject 文件,问题就消失了,我留下这个答案以提醒发生了什么。

【讨论】:

【参考方案10】:

我也面临同样的问题。我正在尝试为 Cyclone V FPGA-SoC 构建 linux 应用程序。我遇到了如下问题:

错误: 使用 VFP 寄存器参数,main.o 不使用

我使用的是altera的嵌入式软件设计工具提供的工具链arm-linux-gnueabihf-g++

通过导出解决: mfloat-abi=hard 到标志,然后arm-linux-gnueabihf-g++ 编译没有错误。还包括CCLD 中的标志。

【讨论】:

【参考方案11】:

“请注意,硬浮点和软浮点 ABI 不是链接兼容的;您必须使用相同的 ABI 编译整个程序,并与一组兼容的库链接。” https://gcc.gnu.org/onlinedocs/gcc/ARM-Options.html arm-none-eabi-gcc.exe

Silicon Labs “kjostera” “Employee” 对 EFR32 Flex Gecko(交叉引用 Cortex-M4F)的回应:“因此,使用 softfp ABI 编译的代码与使用 hardfp ABI 编译的代码的链接时间不兼容。因此,由于我们目前仅支持 RAIL使用 softfp ABI 编译的库,这意味着您还必须使用 softfp ABI 构建应用程序。” “注意,使用softfp ABI并不意味着你的代码不能使用FPU指令。任何做浮点运算的代码都会在编译器认为有意义的时候使用FPU。” “kjostera”然后继续证明 GCC 7 为-mfloat-abi=softfp-mfloat-abi=hard 的情况生成了程序集,调用了vmul.f32 指令,指令计数为10 用于softfp,9 用于hard . https://www.silabs.com/community/mcu/32-bit/forum.topic.html/enable_fpu_in_rail-p-SEYrhttps://www.silabs.com/documents/public/data-sheets/efr32fg1-datasheet.pdfhttps://www.silabs.com/documents/public/reference-manuals/efr32xg12-rm.pdfhttps://www.silabs.com/documents/public/reference-manuals/efr32xg13-rm.pdfhttps://www.silabs.com/documents/public/reference-manuals/efr32xg14-rm.pdf

【讨论】:

【参考方案12】:

这个问题的另一个原因是你省略了最终二进制目标的 cpu 架构规范。

例如,即使您的-mfloat-abi-mfpu 开关在所有模块和最终二进制文件之间都一致,您仍然可能在-mcpu 上被绊倒。

在我的例子中,在最终二进制文件中省略 -mcpu=cortex-m4 会导致链接器默认使用其他一些 cpu 架构。这也产生了关于 VFP 寄存器的相同消息。

【讨论】:

【参考方案13】:

通过将我的项目与 Raspberry 的一些外部库静态链接,我遇到了类似的问题。任何提到的编译器选项都可以提供帮助。通过比较我的目标文件和我正在链接的静态库的目标文件的 readelf 输出,我开始使用另一个交叉编译器。使用与以前相同的编译器选项,问题不再出现。所以,也许您只需要使用正确的交叉编译器,支持正确的 ABI 版本。

作为提示,ABI 版本编码在您主机上的编译器名称中。

【讨论】:

以上是关于ARM编译错误,可执行文件使用的VFP寄存器,而不是目标文件的主要内容,如果未能解决你的问题,请参考以下文章

ARM pwn 入门

ARM11 S3C6410 硬件浮点(VFP)实现

vfp程序运行出现错误 想忽略错误继续执行 用啥命令

编译出arm Android环境下的C++可执行文件

在Linux PC上查看arm交叉编译的可执行文件依赖的动态库

如何在编译期间编辑可执行文件而不更改其源? [复制]