手臂皮层a9交叉编译奇怪的浮点行为 [英] arm cortex a9 cross compiling strange floating point behaviour
问题描述
所以我尝试了这个小测试程序,它也会触发错误。
测试程序的输出结果(见下面)应该证明我的问题。
pre $ #include< iostream>
int main(int argc,char * argv [])
{
double x = 80;
double y = 0;
std :: cout<< x<< \t<< y<的std :: ENDL;
返回0;
}
在arm cortex a9编译:
@ tegra $ g ++ -Wall test.cpp -o test_nativ
@ tegra $ ./test_nativ
80 0
$ b交叉编译
$ b $@ 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
请参阅:http://pastebin.com/3kqHHLgQ
@ tegra $ objdump -S test_nativ
请参阅:http://pastebin.com/zK35KL4X
。
回答下面的一些评论:
- 交叉编译器设置为小端,就像本地编译器o一样在Tegra机器上。
- 我不相信它是一个内存对齐问题,当我移植到这些应用程序时,这些应该发送SIGBUS到应用程序或登录到syslog,请参阅/ proc的文档/ cpu / alignment。
我目前的解决方法是复制交叉编译的工具链,并使用它LD_LIBRARY_PATH ...不好,但足够好暂时。
谢谢你的答案。
在此期间,我发现tegra设备上的linux发行版是通过'-mfloat-abi = softfp'编译的,虽然文档说明了,用'-mfloat-abi = hard'编译的工具链是必需的。
更改工具链带来了成功。
似乎可以在任何系统二进制文件中使用'readelf -A'来查看hard和softfp之间的区别:
如果Output包含该行:'Tag_ABI_VFP_args:VFP寄存器'它是用'-mfloat-abi = hard'编译的。如果缺少这一行,那么二进制文件很可能是用-mfloat-abi = softfp编译的。
'Tag_ABI_HardFP_use:SP和DP'并不表示编译器标记'-mfloat-abi = hard'。
解决方案看看程序集的输出,我们可以看到两个文件有差异。
在
test_nativ < code $:b
$ b $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ b 86f0:f241 0044 movw r0,#4164; 0x1044
86f4:f2c0 0001 movt r0,#1
86f8:f7ff ef5c blx 85b4< _init + 0x20>
在<$中传递
double
在r0
中的c $ c> r2:r3 和std :: cout
/ p>
在
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>
在<$ c中传递
double
$ c $ d> c code>(一个VFP寄存器)和std :: cout
在r0
。在这里可以看到r2:r3
被加载(通过ldrd
),浮点值被打印出来, 0.0。因为动态链接的ostream :: operator <?((double val)
)在r2:r3
0打印出来。
我可以解释第二个怪异的浮点数。这里是第二个浮动的地方:
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,它以double的形式解码为1.478946186471156e-309。
所以问题在于你的桌面GCC的库使用VFP / NEON指令,而这些指令并没有被设备上的动态库所使用。如果你使用
-static
,你可以得到VFP / NEON库,一切都可以正常运行。
我的建议是只是要弄清楚为什么设备和编译器库有所不同,并将其整理出来。
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).
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:
@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.
@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.
- 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.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.
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.
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:
If the Output contains the line: 'Tag_ABI_VFP_args: VFP registers' it is compiled with '-mfloat-abi=hard'. If this line is missing the binary is most likely compiled with '-mfloat-abi=softfp'.
The line 'Tag_ABI_HardFP_use: SP and DP' does not indicate the compilerflag '-mfloat-abi=hard'.解决方案Looking at the assembly output, we can see a discrepancy in the two files.
In
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
inr2:r3
, andstd::cout
inr0
.In
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
ind0
(a VFP register), andstd::cout
inr0
. Observe here thatr2:r3
is loaded (byldrd
) with the floating point value that is printed out second, i.e. 0.0. Because the dynamically-linkedostream::operator<<(double val)
expects its argument inr2:r3
, 0 is printed out first.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 tor0
, the address ofcout
. From above,r0 = 0x011040
. Thus, the register pairr2:r3
becomes 0x0001104000000000, which decodes to 1.478946186471156e-309 as a 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. If you use
-static
, you get the VFP/NEON libraries, and everything works again.My suggestion would just be to figure out why the device and compiler libraries differ, and get that sorted out.
这篇关于手臂皮层a9交叉编译奇怪的浮点行为的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!
查看全文