首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >交叉编译QT4.7时的“非法指令”

交叉编译QT4.7时的“非法指令”
EN

Stack Overflow用户
提问于 2011-04-11 12:40:31
回答 2查看 4.6K关注 0票数 8

我已经为这个问题挣扎了一个多星期了,仍然找不到解决办法.

我试图交叉编译QT4.7嵌入式开源版本的ARM设备.构建过程本身没有问题地完成,但是生成的二进制文件似乎包含处理器不理解的指令。

  • 构建主机是i386上的Debian 5 (Etch) (运行在虚拟PC上)。
  • 该设备为Trimble Nomad,手持ARM处理器(见完整的cpuinfo内核配置)。
  • 我使用为设备制作的原始构建工具链,到目前为止运行良好(甚至可以成功地构建咬咬 )-请参阅编译器设置和版本
  • 我使用的是基于qmake.conf的自定义linux-arm-gnueabi-g++,并适应于使用正确的工具链-- 请参阅这里的源代码
  • 通过将部分改进添加到编译器标志中,我得到了一个,但是在(一些)情况下,仍然会出现“非法指令”错误(但至少这是一个很大的改进)。
  • 二进制文件本身基本上可以工作,但在某些情况下,程序会因“非法指令”错误而崩溃。我相信这发生在某些浮点操作时,做图形的东西。
  • 添加-mcpu=xscale-march=armv4-O0-march=armv4-mtune=arm920t (并非全部同时)丝毫没有帮助。
  • 使用--debug标志构建Qt似乎解决了所有问题(),但是添加-O2标志会重新引入这些问题。奇怪的是,没有--调试的-O0设置没有帮助。
  • 编译后的configuremake输出可以看到这里。除了据说它们是编译器的错误警告。,还有很多对齐警告。
  • QT4.7.2中肯定有一些更改,因为早期版本(4.7.1、4.7.0)确实运行良好的

configure设置:

代码语言:javascript
复制
  ./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 

坠机前的绞刑:

代码语言:javascript
复制
$ 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

崩溃的gdb回溯(我缺少调试符号,因为用调试信息编译可以解决问题):

代码语言:javascript
复制
(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)

注意,该设备附带Qtopia4.3预装,供应商也无法解释我的构建的问题。

更新

在Igor Skochinsky的帮助下,我可以找到导致SIGILL的确切汇编程序指令。由于某些原因,指令在导致错误之前工作了47次。请参见下面的gdb输出(注意,我一点也不熟悉ARM汇编程序):

代码语言:javascript
复制
$ 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

有什么建议我可以尝试的吗?

EN

回答 2

Stack Overflow用户

发布于 2011-04-11 13:27:27

拆卸装配非常有趣。

代码语言:javascript
复制
 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

代码检查fpscr中的位9,如果设置,则尝试保存寄存器f2-f7。那些是什么?我从未在最近的处理器中见过它们,但我认为它们是FPA (“浮点加速器”)寄存器,在几个旧内核中实现,并在VFP出现之前用于软FP。

所以,我认为会发生这样的事情:

  1. 您的设备上的libc是在FPA支持下编译的,可能是错误的。
  2. 在FPA处理器中,位9指的是"FPA启用“或类似的东西。
  3. 在Qt的调试版本中,没有设置FPSCR的位9 (DZE =除以零异常启用位),因此它们不试图保存FPA寄存器。但是,它会在发行版中设置。

我在这里看到两种选择:

  1. 重建libc而不需要FPA支持
  2. 查找DZE在发行版中设置的位置(不确定如何设置)

更新:我错了。gdb把我搞糊涂了。我找到了setjmp.S的来源,下面是相关的部分:

代码语言:javascript
复制
        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:

因此,它试图存储的是WMMXt寄存器,而不是FPA。然而,这里有一个bug。它使用r2临时存储fpscr,,但是用a3 (a3是r2的装甲运兵车名称 )写入以前加载的hwcap值的。也许作者打算使用a2,而不是r2,或者这两个部分是由不同的人完成的。在任何一种情况下,Qt的发布版本都会改变FPSCR (这很可能是内核模仿的),并触发存储iwmmxt的代码。

不过,这还不是全部。hwcaps 你粘了声称CPU支持iWMMXt,所以我不知道为什么这些指令会带来麻烦。也许报告的PC值是错误的。我认为您应该尝试在__sigsetjmp上放置断点,并通过指令(第一步)遍历它,以查看它到底在哪里崩溃。

票数 4
EN

Stack Overflow用户

发布于 2016-12-30 19:08:16

你好,几天前我遇到了类似的问题.但是我在VMware播放器(不是ARM设备)中的Slackware Linux上运行Qt 5.7。

安装成功后,我无法启动Qt。我尝试使用下面的终端命令/opt/Qt5.7.0/Tools/QtCreator/bin/qtcreator运行Qt,它给了我一个错误Illegal instruction

在谷歌工作了几个小时之后,我尝试用这个终端命令/opt/Qt5.7.0/Tools/QtCreator/bin/qtcreator -noload Welcome运行Qt,这对我来说是有效的。

希望这能帮上忙。抱歉反应晚了。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/5621393

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档