Udo*_*o G 8 qt arm cross-platform cross-compiling
我现在已经在这个问题上挣扎了一个多星期了,仍然无法找到解决方案......
我正在尝试为ARM设备交叉编译Qt 4.7嵌入式开源版本.构建过程本身完成没有问题,但生成的二进制文件似乎包含处理器不理解的指令.
qmake.conf基于linux-arm-gnueabi-g++并使用正确工具链的自定义- 请参阅此处的源代码-msoft-float -D__GCC_FLOAT_NOT_NEEDED但在某些情况下仍然会出现" 非法指令 "错误(但至少这是一个很大的改进)-mcpu=xscale,-march=armv4,-O0,-march=armv4,-mtune=arm920t(不是全部在同一时间)以任何方式没有帮助.--debug标志构建Qt 似乎可以解决所有问题,但添加-O2标志会重新引入它们.奇怪的-O0设置不 --debug并没有帮助.configure和make输出.有很多对齐警告,但据说它们是编译器的错误警告.configure 设置:
./configure \
-embedded arm \
-xplatform qws/linux-arm-angstrom-gnueabi-g++ \
-debug \
-no-largefile \
-no-multimedia \
-no-audio-backend \
-no-phonon \
-no-phonon-backend \
-webkit \
-javascript-jit \
-no-xshape \
-no-xvideo \
-no-xsync \
-no-xinerama \
-no-xcursor \
-no-xfixes \
-no-xrandr \
-no-xrender \
-no-xinput \
-no-xkb \
-no-opengl \
-nomake docs \
-nomake examples \
-nomake tools \
-nomake demos \
-nomake translations \
-opensource \
-qt-mouse-tslib \
-qt-libjpeg \
-qt-gif
Run Code Online (Sandbox Code Playgroud)
坠机前的strace:
$ LD_LIBRARY_PATH=. QT_QWS_FONTDIR=$PWD/fonts QT_PLUGIN_PATH=$PWD/plugins QWS_MOUSE_PROTO=tslib:/dev/input/touchscreen0 strace ./digitalclock -qws test.htm
...
lseek(15, 0, SEEK_END) = 16998
write(15, "\t\n\f\0\367\t", 6) = 6
write(15, "\0\0+\234\325\343\306{\3\0\0\0\0J\370\377\351\301\336\377"..., 120) = 120
lseek(15, 0, SEEK_END) = 17124
write(15, "\10\10\10\0\371\10", 6) = 6
write(15, "\0\6j\251\260\201\27\0\2\276\377\351\334\377\346\32K\377"..., 64) = 64
lseek(15, 0, SEEK_END) = 17194
write(15, "\7\10\10\0\371\7", 6) = 6
write(15, "\0\4c\245\263\224 \0\1\271\377\367\315\356P\0I\377\364"..., 64) = 64
lseek(15, 0, SEEK_END) = 17264
write(15, "\10\n\10\1\366\10", 6) = 6
write(15, "\37 \3\0\0\0\0\0\374\377\34\0\0\0\0\0\374\377\34\0\0\0"..., 80) = 80
fcntl64(15, F_SETLK, {type=F_UNLCK, whence=SEEK_SET, start=0, len=0}) = 0
lseek(15, 0, SEEK_END) = 17350
mremap(0x415f5000, 16552, 17350, MREMAP_MAYMOVE) = 0x415f5000
--- SIGILL (Illegal instruction) @ 0 (0) ---
rt_sigaction(SIGILL, {SIG_DFL}, {0x401b7d34, [ILL], SA_RESTART|0x4000000}, 8) = 0
socket_subcall(0x1f8004, 0, 0x100, 0, 0, 0x18844, 0x18840, 0x12c) = 0
ioctl(12, KDSKBMODE, 0x2) = 0
ioctl(12, SNDCTL_TMR_START or TCSETS, {B38400 -opost -isig -icanon -echo ...}) = 0
close(12) = 0
ioctl(10, KDSETMODE, 0x1) = 0
write(10, "\33[9;15]\33[?33h\33[?25h\33[?0c\0", 25) = 25
close(10) = 0
statfs64(umovestr: Input/output error
0x6d4f, 27983, {???}) = 0
sigreturn() = ? (mask now [ILL ABRT BUS FPE USR1 SEGV USR2 PIPE STKFLT CHLD CONT STOP TTOU URG XCPU VTALRM PROF WINCH IO PWR RTMIN])
--- SIGILL (Illegal instruction) @ 0 (0) ---
+++ killed by SIGILL +++
Process 27983 detached
Run Code Online (Sandbox Code Playgroud)
崩溃的gdb回溯(由于使用调试信息进行编译,我缺少调试符号)解决了这个问题:
(gdb) run -qws
Starting program: /home/.qt-test2/digitalclock -qws
Program received signal SIGILL, Illegal instruction.
0x4130268c in __sigsetjmp () from /lib/libc.so.6
(gdb) bt
#0 0x4130268c in __sigsetjmp () from /lib/libc.so.6
#1 0x4046ee5c in ?? () from ./libQtGui.so.4
(gdb)
Run Code Online (Sandbox Code Playgroud)
请注意,该设备预装了Qtopia 4.3,供应商也无法解释我的构建问题.
在Igor Skochinsky的帮助下,我可以找到导致SIGILL的确切汇编指令.由于某种原因,指令在导致错误之前可以正常工作47次.请参阅gdb下面的输出(注意我根本不熟悉ARM汇编程序):
$ LD_LIBRARY_PATH=. QT_QWS_FONTDIR=$PWD/fonts QT_PLUGIN_PATH=$PWD/plugins QWS_MOUSE_PROTO=tslib:/dev/input/touchscreen0 gdb ./digitalclock
GNU gdb 6.6
Copyright (C) 2006 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB. Type "show warranty" for details.
This GDB was configured as "arm-angstrom-linux-gnueabi"...
Using host libthread_db library "/lib/libthread_db.so.1".
(gdb) start -qws
Breakpoint 1 at 0xaa58: file main.cpp, line 47.
Starting program: /home/.qt-test2/digitalclock -qws
[Thread debugging using libthread_db enabled]
[New Thread 1073870720 (LWP 2799)]
[Switching to Thread 1073870720 (LWP 2799)]
main (argc=2, argv=0xbea17d04) at main.cpp:47
47 main.cpp: No such file or directory.
in main.cpp
(gdb) display/i $pc
1: x/i $pc 0xaa58 <main+24>: sub r3, r11, #28 ; 0x1c
(gdb) display/x $r2
2: /x $r2 = 0xbea17d10
(gdb) display/x $f2
3: /x $f2 = 0x0
(gdb) b *0x41302684
Breakpoint 2 at 0x41302684
(gdb) continue
Continuing.
---> no problem here:
Breakpoint 2, 0x41302684 in __sigsetjmp () from /lib/libc.so.6
3: /x $f2 = 0x0
2: /x $r2 = 0x293
1: x/i $pc 0x41302684 <__sigsetjmp+52>: beq 0x413026a0 <Lno_iwmmxt>
(gdb) si
0x41302688 in __sigsetjmp () from /lib/libc.so.6
3: /x $f2 = 0x0
2: /x $r2 = 0x293
1: x/i $pc 0x41302688 <__sigsetjmp+56>: stfp f2, [r12], #8
(gdb) si
0x4130268c in __sigsetjmp () from /lib/libc.so.6
3: /x $f2 = 0x0
2: /x $r2 = 0x293
1: x/i $pc 0x4130268c <__sigsetjmp+60>: stfp f3, [r12], #8
(gdb) si
0x41302690 in __sigsetjmp () from /lib/libc.so.6
3: /x $f2 = 0x0
2: /x $r2 = 0x293
1: x/i $pc 0x41302690 <__sigsetjmp+64>: stfp f4, [r12], #8
(gdb) continue
Continuing.
Breakpoint 2, 0x41302684 in __sigsetjmp () from /lib/libc.so.6
3: /x $f2 = 0x0
2: /x $r2 = 0x293
1: x/i $pc 0x41302684 <__sigsetjmp+52>: beq 0x413026a0 <Lno_iwmmxt>
(gdb) continue 46
Will ignore next 45 crossings of breakpoint 2. Continuing.
---> __sigsetjmp still working fine, but then:
Breakpoint 2, 0x41302684 in __sigsetjmp () from /lib/libc.so.6
3: /x $f2 = 0x0
2: /x $r2 = 0x293
1: x/i $pc 0x41302684 <__sigsetjmp+52>: beq 0x413026a0 <Lno_iwmmxt>
(gdb) si
0x41302688 in __sigsetjmp () from /lib/libc.so.6
3: /x $f2 = 0x0
2: /x $r2 = 0x293
1: x/i $pc 0x41302688 <__sigsetjmp+56>: stfp f2, [r12], #8
(gdb) si
Program received signal SIGILL, Illegal instruction.
0x4130268c in __sigsetjmp () from /lib/libc.so.6
3: /x $f2 = 0x0
2: /x $r2 = 0x293
1: x/i $pc 0x4130268c <__sigsetjmp+60>: stfp f3, [r12], #8
Run Code Online (Sandbox Code Playgroud)
有什么建议我接下来可以尝试吗?
发布的拆解非常有趣。
0x41302678 <__sigsetjmp+40>: fmrx r2, fpscr
0x4130267c <__sigsetjmp+44>: str r2, [r12], #4
0x41302680 <__sigsetjmp+48>: tst r2, #512 ; 0x200
0x41302684 <__sigsetjmp+52>: beq 0x413026a0 <__sigsetjmp+80>
0x41302688 <__sigsetjmp+56>: stfp f2, [r12], #8
*0x4130268c <__sigsetjmp+60>: stfp f3, [r12], #8*
0x41302690 <__sigsetjmp+64>: stfp f4, [r12], #8
0x41302694 <__sigsetjmp+68>: stfp f5, [r12], #8
0x41302698 <__sigsetjmp+72>: stfp f6, [r12], #8
0x4130269c <__sigsetjmp+76>: stfp f7, [r12], #8
Run Code Online (Sandbox Code Playgroud)
该代码检查 fpscr 中的位 9,如果设置,则尝试保存寄存器 f2-f7。那些是什么?我从未在最近的处理器中见过它们,但我认为这些是 FPA(“浮点加速器”)寄存器,在一些旧内核中实现,并在 VFP 出现之前用于软 FP。
所以,我认为会发生以下情况:
我在这里看到两个选项:
更新:我错了。gdb 反汇编让我很困惑。我找到了setjmp.S的来源,这是相关部分:
tst a3, #HWCAP_ARM_VFP
beq Lno_vfp
/* Store the VFP registers. */
/* Following instruction is fstmiax ip!, {d8-d15}. */
stc p11, cr8, [r12], #68
/* Store the floating-point status register. */
/* Following instruction is fmrx r2, fpscr. */
mrc p10, 7, r2, cr1, cr0, 0
str r2, [ip], #4
Lno_vfp:
tst a3, #HWCAP_ARM_IWMMXT
beq Lno_iwmmxt
/* Save the call-preserved iWMMXt registers. */
/* Following instructions are wstrd wr10, [ip], #8 (etc.) */
stcl p1, cr10, [r12], #8
stcl p1, cr11, [r12], #8
stcl p1, cr12, [r12], #8
stcl p1, cr13, [r12], #8
stcl p1, cr14, [r12], #8
stcl p1, cr15, [r12], #8
Lno_iwmmxt:
Run Code Online (Sandbox Code Playgroud)
因此,它尝试存储 WMMXt 寄存器,而不是 FPA。然而,这里有一个错误。它使用 r2 临时存储 fpscr,但这会覆盖 a3 中先前加载的 hwcap 值(a3 是r2 的APCS 名称)。也许作者打算使用a2,而不是r2,或者这两个部分可能是由不同的人完成的。无论哪种情况,Qt 的发布版本都会以某种方式更改 FPSCR(很可能由内核模拟)并触发存储 iwmmxt regs 的代码。
但这还不是故事的全部。您粘贴的hwcaps声称 CPU 确实支持 iWMMXt,所以我不确定为什么这些指令会带来麻烦。也许报告的 PC 值在某种程度上是错误的。我认为您应该尝试在 __sigsetjmp 上放置断点并通过指令(stepi)逐步执行它,以查看它到底在哪里崩溃。
| 归档时间: |
|
| 查看次数: |
4101 次 |
| 最近记录: |