简体   繁体   English

手臂皮质a9交叉编译奇怪的浮点行为

[英]arm cortex a9 cross compiling strange floating point behaviour

I am trying to port a larger application from x86 to arm cortex a9, but I'm getting strange segmentation faults with floating point functions like modf when cross compiling the application, other libc++ functions just seem to handle floats wrong, but don't crash(see below). 我试图将一个更大的应用程序从x86移植到arm cortex a9,但是当交叉编译应用程序时,我得到了像modf这样的浮点函数的奇怪分段错误,其他libc ++函数似乎只是处理浮动错误,但不会崩溃(见下文)。

So I tried this small test programm, which can trigger the error too. 所以我尝试了这个小测试程序,它也可以触发错误。 The output of the test programm(see below) should demonstrate my problem. 测试程序的输出(见下文)应该证明我的问题。

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

compiled on arm cortex a9: 编译在arm cortex a9上:

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

cross compiled 交叉编译

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

cross compiled with '-static' linker option. 使用'-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

.

To answer some of the comments below: 要回答以下一些评论:
- Cross compiler is setup for little endian, as is the native compiler on the tegra machine. - 交叉编译器是为小端设置的,就像tegra机器上的本机编译器一样。
- I don't believe its a memory alignment issue, had my share of these while porting to arm and these should send SIGBUS to application or log to syslog, see documentation for /proc/cpu/alignment. - 我不相信它的内存对齐问题,在移植到arm时有我的共享,这些应该将SIGBUS发送到应用程序或登录到syslog,请参阅/ proc / cpu / alignment的文档。

My current workaround is to copy over the crosscompiled toolchain and use it with LD_LIBRARY_PATH ... not nice, but good enough for the time being. 我目前的解决方法是复制交叉编译的工具链并将其与LD_LIBRARY_PATH一起使用......不是很好,但暂时还不错。




Edit: 编辑:
Thank you for your Answers. 谢谢您的回答。
In the meantime I found out that the linux distribution on the tegra device was compiled with '-mfloat-abi=softfp' though the documentation stated, that a toolchain compiled with '-mfloat-abi=hard' is required. 与此同时,我发现tegra设备上的linux发行版是使用'-mfloat-abi = softfp'编译的,尽管文档说明,需要使用'-mfloat-abi = hard'编译的工具链。
Changing the toolchain brought the success. 改变工具链带来了成功。

It seems that the difference between hard and softfp can be seen using 'readelf -A' on any system binary: 似乎在任何系统二进制文件上使用'readelf -A'可以看出hard和softfp之间的区别:
If the Output contains the line: 'Tag_ABI_VFP_args: VFP registers' it is compiled with '-mfloat-abi=hard'. 如果输出包含行:'Tag_ABI_VFP_args:VFP寄存器',则使用'-mfloat-abi = hard'编译。 If this line is missing the binary is most likely compiled with '-mfloat-abi=softfp'. 如果缺少此行,则二进制文件很可能使用'-mfloat-abi = softfp'编译。
The line 'Tag_ABI_HardFP_use: SP and DP' does not indicate the compilerflag '-mfloat-abi=hard'. 行'Tag_ABI_HardFP_use:SP和DP'不表示编译标志'-mfloat-abi = hard'。

Looking at the assembly output, we can see a discrepancy in the two files. 查看汇编输出,我们可以看到两个文件中的差异。

In test_nativ : 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>

This is passing a double in r2:r3 , and std::cout in r0 . 这是在r2:r3传递一个double ,在r0传递std::cout

In test_cc : 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>

This passes a double in d0 (a VFP register), and std::cout in r0 . 这在d0 (VFP寄存器)中传递了一个double ,在r0传递了std::cout Observe here that r2:r3 is loaded (by ldrd ) with the floating point value that is printed out second, ie 0.0. 这里观察到r2:r3被加载(通过ldrd ),其浮点值被打印出来,即第二个,即0.0。 Because the dynamically-linked ostream::operator<<(double val) expects its argument in r2:r3 , 0 is printed out first. 因为动态链接的ostream::operator<<(double val)期望其参数在r2:r3 ,所以首先打印出0。

I can explain the second weird-looking float too. 我也可以解释第二个奇怪的浮动。 Here's where the second float is printed: 这是打印第二个浮点数的位置:

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

See that r3 is set to r0 , the address of cout . 看到r3设置为r0cout的地址。 From above, r0 = 0x011040 . 从上面看, r0 = 0x011040 Thus, the register pair r2:r3 becomes 0x0001104000000000, which decodes to 1.478946186471156e-309 as a double. 因此,寄存器对r2:r3变为0x0001104000000000,其解码为1.478946186471156e-309为double。

So the problem is that your desktop GCC's libraries uses VFP/NEON instructions, which are not used by the on-device dynamic libraries. 所以问题是您的桌面GCC库使用VFP / NEON指令,这些指令不会被设备上的动态库使用。 If you use -static , you get the VFP/NEON libraries, and everything works again. 如果使用-static ,则会获得VFP / NEON库,一切都可以正常工作。

My suggestion would just be to figure out why the device and compiler libraries differ, and get that sorted out. 我的建议只是弄清楚为什么设备和编译器库不同,并将其整理出来。

My guess : Without proper switches indicating vfp hardware support, the compiler will use software libraries to do floating point math on arm. 我的猜测 :如果没有正确的开关指示vfp硬件支持,编译器将使用软件库在手臂上进行浮点数学运算。 If you compile with static linking, these libraries will get included into binary -- result: it works. 如果使用静态链接进行编译,这些库将包含在二进制文件中 - 结果:它可以工作。 If you use normal (dynamic) linking mode the libraries do not get included -- result: it does not work for some reason. 如果使用普通(动态)链接模式,则不会包含库 - 结果:由于某种原因它不起作用。 The libraries on your tegra system are somehow incompatibile (probably due to calling convention) with what your crosscompiler is producing. tegra系统上的库与您的交叉编译器生成的内容在某种程度上是不兼容的(可能是由于调用约定)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM