gpt4 book ai didi

qt - "Illegal instruction"交叉编译 Qt 4.7 时

转载 作者:行者123 更新时间:2023-12-04 08:37:59 25 4
gpt4 key购买 nike

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

我正在尝试为 ARM 设备交叉编译 Qt 4.7 嵌入式开源版本。构建过程本身毫无问题地完成,但生成的二进制文件似乎包含处理器不理解的指令。

  • 构建主机是 i386 上的 Debian 5 (Etch)(在虚拟 PC 上运行)
  • 该设备是带有 ARM 处理器的 Trimble Nomad 手持设备(see full cpuinfokernel configuration)
  • 我使用为设备制作的原始构建工具链,迄今为止运行良好(甚至可以成功构建 Gnash) - 参见 compiler settings and version
  • 我正在使用自定义 qmake.conf基于 linux-arm-gnueabi-g++并适应使用正确的工具链 - see source code here
  • 我有一个 局部改进通过添加 -msoft-float -D__GCC_FLOAT_NOT_NEEDED到编译器标志,但我仍然收到“ 非法指令 ” 错误 一些 情况(但至少这是一个很大的改进)
  • 二进制文件本身基本上可以工作,但在某些情况下,程序会因“非法指令”错误而崩溃。我相信这会发生在某些浮点运算中,同时进行图形处理。
  • 添加 -mcpu=xscale , -march=armv4 , -O0 , -march=armv4 , -mtune=arm920t (并非全部在同一时间)没有任何帮助。
  • 使用 --debug 构建 Qt旗似乎解决了所有问题 但添加 -O2 flag 重新介绍了它们。奇怪的是-O0没有 --debug 的设置是 不是 帮助。
  • 编译configuremake可以看到输出here .有很多对齐警告,但 they are said to be false warnings of the compiler .
  • 肯定有一些变化Qt 4.7.2 因为 早期版本 (4.7.1, 4.7.0) 运行良好 .
  • 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

    崩溃前的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

    崩溃的 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)

    请注意,该设备预装了 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

    有什么建议我接下来可以尝试吗?

    最佳答案

    posted disassembly很有趣。

     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。

    所以,这就是我认为会发生的事情:
  • 您设备上的 libc 已编译
    有 FPA 支持,可能由
    错误。
  • 在 FPA 处理器中位 9
    意思是“启用 FPA”或其他东西
    类似
  • 在 Qt 的调试版本中
    FPSCR 的第 9 位(DZE = 除法
    零异常使能位)不是
    设置,所以他们不会试图保存 FPA
    寄存器。然而,它被设置在
    发布版本。

  • 我在这里看到两个选项:
  • 在不支持 FPA 的情况下重建 libc
  • 找到 DZE 在发行版中的设置位置(不知道怎么做)


  • 更新 : 我错了。 gdb 的反汇编让我很困惑。我找到了 the source 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:

    因此,它试图存储 WMMXt 寄存器,而不是 FPA。但是,这里有一个错误。它使用 r2 临时存储 fpscr, 但是 在 a3 中覆盖先前加载的 hwcap 值(a3 是 r2 的 APCS name)。也许作者打算使用a2,而不是r2,或者这两个部分是由不同的人完成的。在任何一种情况下,Qt 的发布版本都会以某种方式更改 FPSCR(这很可能由内核模拟)并且存储 iwmmxt regs 的代码被触发。

    不过,这还不是故事的全部。 hwcaps you pasted声称 CPU 确实支持 iWMMXt,所以我不确定为什么这些指令会带来麻烦。也许报告的 PC 值在某种程度上是错误的。我认为您应该尝试在 __sigsetjmp 上放置断点并通过指令 (stepi) 单步执行,以查看它到底在哪里崩溃。

    关于qt - "Illegal instruction"交叉编译 Qt 4.7 时,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5621393/

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