gpt4 book ai didi

c++ - arm cortex a9 交叉编译奇怪的浮点行为

转载 作者:可可西里 更新时间:2023-11-01 18:37:58 39 4
gpt4 key购买 nike

我正在尝试将一个更大的应用程序从 x86 移植到 arm cortex a9,但是当交叉编译应用程序时,我遇到了像 modf 这样的浮点函数的奇怪段错误,其他 libc++ 函数似乎只是错误地处理 float ,但是不要不会崩溃(见下文)。

所以我尝试了这个小测试程序,它也可以触发错误。测试程序的输出(见下文)应该可以证明我的问题。

#include <iostream>
int main(int argc, char *argv[])
{
double x = 80;
double y = 0;
std::cout << x << "\t" << y << std::endl;
return 0;
}

在 arm cortex a9 上编译:

@tegra$ g++ -Wall test.cpp -o test_nativ
@tegra$ ./test_nativ
80 0

交叉编译

@x86$ arm-cortex_a9-linux-gnueabi-g++ test.cpp  -o test_cc
@tegra$ ./test_cc
0 1.47895e-309

使用“-static”链接器选项交叉编译。

@x86$ arm-cortex_a9-linux-gnueabi-g++ -static test.cpp  -o test_cc_static
@tegra$ ./test_cc_static
80 0

.

@x86$ arm-cortex_a9-linux-gnueabi-objdump -S test_cc
see: http://pastebin.com/3kqHHLgQ

@tegra$ objdump -S test_nativ
see: http://pastebin.com/zK35KL4X

.

回答下面的一些评论:
- 交叉编译器是为小端设置的,就像 tegra 机器上的本地编译器一样。
- 我不认为这是内存对齐问题,我在移植到 arm 时分享了这些,这些应该将 SIGBUS 发送到应用程序或记录到系统日志,请参阅/proc/cpu/alignment 的文档。

我目前的解决方法是复制交叉编译的工具链并将其与 LD​​_LIBRARY_PATH 一起使用……不太好,但暂时足够了。




编辑:
感谢您的回答。
与此同时,我发现 tegra 设备上的 linux 发行版是使用“-mfloat-abi=softfp”编译的,尽管文档中指出,需要使用“-mfloat-abi=hard”编译的工具链。
改变工具链带来了成功。

似乎可以在任何系统二进制文件上使用“readelf -A”来查看 hard 和 softfp 之间的区别:
如果输出包含以下行:“Tag_ABI_VFP_args: VFP registers”,则使用“-mfloat-abi=hard”进行编译。如果缺少此行,二进制文件很可能是使用“-mfloat-abi=softfp”编译的。
“Tag_ABI_HardFP_use: SP and DP”这一行并不表示编译器标志“-mfloat-abi=hard”。

最佳答案

查看程序集输出,我们可以看到两个文件存在差异。

test_nativ :

86ec:       4602            mov     r2, r0
86ee: 460b mov r3, r1
86f0: f241 0044 movw r0, #4164 ; 0x1044
86f4: f2c0 0001 movt r0, #1
86f8: f7ff ef5c blx 85b4 <_init+0x20>

这是传递 doubler2:r3 , 和 std::coutr0 .

test_cc :

86d8:       e28f3068        add     r3, pc, #104    ; 0x68
86dc: e1c320d0 ldrd r2, [r3]
86e0: e14b21f4 strd r2, [fp, #-20] ; 0xffffffec
86e4: e3010040 movw r0, #4160 ; 0x1040
86e8: e3400001 movt r0, #1
86ec: ed1b0b03 vldr d0, [fp, #-12]
86f0: ebffffa5 bl 858c <_init+0x20>

这传递了一个 doubled0 (一个 VFP 寄存器),和 std::coutr0 .在这里观察 r2:r3加载(由 ldrd )第二个打印出来的浮点值,即 0.0.因为动态链接 ostream::operator<<(double val)期望其参数在 r2:r3 中, 0 先打印出来。

我也可以解释第二个看起来很奇怪的 float 。这是打印第二个 float 的地方:

8708:       e1a03000        mov     r3, r0
870c: e1a00003 mov r0, r3
8710: ed1b0b05 vldr d0, [fp, #-20] ; 0xffffffec
8714: ebffff9c bl 858c <_init+0x20>

看到r3设置为 r0 , cout 的地址.从上面看,r0 = 0x011040 .因此,寄存器对 r2:r3变为 0x0001104000000000,解码为 1.478946186471156e-309 作为 double 值。

所以问题是您的桌面 GCC 库使用 VFP/NEON 指令,而设备上的动态库不使用这些指令。如果你使用 -static ,您将获得 VFP/NEON 库,然后一切又恢复正常。

我的建议是找出设备库和编译器库不同的原因,然后解决这个问题。

关于c++ - arm cortex a9 交叉编译奇怪的浮点行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12800525/

39 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com