«Недопустимая инструкция» при кросс-компиляции Qt 4.7 - PullRequest
8 голосов
/ 11 апреля 2011

Я борюсь с этой проблемой уже более недели, и до сих пор не могу найти решение ...

Я пытаюсь кросс-компилировать встроенную версию Qt 4.7 с открытым исходным кодом дляустройство ARM.Сам процесс сборки завершается без проблем, но сгенерированные двоичные файлы, похоже, содержат инструкции, которые процессор не понимает.

  • Хост сборки - это Debian 5 (Etch) на i386 (работает на виртуальном ПК)
  • Устройство представляет собой контроллер Trimble Nomad с процессором ARM ( см. Полную информацию о ядре и )
  • Я использую оригинальный набор инструментов сборки, который былсделано для устройства, и это работало нормально на сегодняшний день (даже может собрать Gnash успешно) - см. настройки компилятора и версия
  • Я использую пользовательский qmake.confоснован на linux-arm-gnueabi-g++ и адаптирован для использования правильной цепочки инструментов - см. исходный код здесь
  • У меня было частичное улучшение путем добавления -msoft-float -D__GCC_FLOAT_NOT_NEEDED к флагам компилятора, но я все еще получаю ошибки " Недопустимая инструкция " в некоторых ситуациях (но по крайней мере это было большим улучшением)
  • Двоичные файлы в основном работаютно в цеВ некоторых ситуациях происходит сбой программы с ошибкой «Недопустимая инструкция».Я полагаю, что это происходит во время определенных операций с плавающей запятой при выполнении графических операций.
  • Добавление -mcpu=xscale, -march=armv4, -O0, -march=armv4, -mtune=arm920t (не все одновременно) непомочь в любом случае.
  • Сборка Qt с флагом --debug , кажется, решает все проблемы , но добавление флага -O2 вновь вводит их.Как ни странно, -O0 параметр без --debug не помогает.
  • Скомпилированный вывод configure и make можно увидеть здесь .Существует много предупреждений о выравнивании, но они, как говорят, являются ложными предупреждениями компилятора .
  • должно быть какое-то изменение в 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, и поставщик может 'Не могу объяснить и проблему с моей сборкой.


Обновление

С помощью Игоря Скочинского я смог найти точную инструкцию на ассемблере, которая вызывает 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

Есть предложения, что можно попробовать дальше?

Ответы [ 2 ]

4 голосов
/ 11 апреля 2011

Выложенная разборка довольно интересна.

 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

Код проверяет бит 9 в fpscr и, если установлен, пытается сохранить регистры f2-f7. Что это? Я никогда не видел их в недавних процессорах, но я думаю это регистры FPA ("ускоритель с плавающей запятой"), реализованные в нескольких старых ядрах и используемые для мягких FP до появления VFP.

Итак, вот что, я думаю, происходит:

  1. libc на вашем устройстве был скомпилирован с поддержкой FPA, вероятно, ошибка.
  2. В процессорах FPA, бит 9 означало "FPA включен" или что-то аналогичный
  3. В отладочной версии Qt бит 9 FPSCR (DZE = Деление по нулевому исключению включить бит) нет установить, чтобы они не пытались сохранить FPA регистры. Тем не менее, это устанавливается в версия выпуска.

Я вижу здесь два варианта:

  1. Перестроить libc без поддержки FPA
  2. Найдите, где DZE устанавливается в версии релиза (не знаю, как это сделать)

Обновление : я ошибся. Разборка 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:

Итак, он пытается сохранить регистры WMMXt, а не FPA. Однако , здесь есть ошибка. Он использует r2 для временного хранения fpscr, , но , который перезаписывает ранее загруженное значение hwcap в a3 (a3 - это имя APCS для r2). Возможно, автор хотел использовать a2, а не r2, или, может быть, две части были сделаны разными людьми. В любом случае, каким-то образом релизная версия Qt изменяет FPSCR (который, скорее всего, эмулируется ядром), и запускается код, хранящий регистры iwmmxt.

Тем не менее, это не вся история. В hwcaps , которые вы вставили , указано, что процессор поддерживает iWMMXt, поэтому я не уверен, почему эти инструкции доставляют проблемы. Возможно, сообщаемое значение ПК неверно. Я думаю, что вы должны попробовать поставить точку останова на __sigsetjmp и пройти через нее по инструкции (stepi), чтобы увидеть, где именно она падает.

0 голосов
/ 30 декабря 2016

Здравствуйте, у меня была похожая проблема несколько дней назад ... Но я запускаю Qt Creator 5.7 на моем Slackware Linux в плеере VMware (не на устройстве ARM).
После успешной установки я не смог запустить Qt Creator. Я попытался запустить Qt Creator с помощью следующей команды терминала /opt/Qt5.7.0/Tools/QtCreator/bin/qtcreator, и она выдала мне ошибку Illegal instruction.
После нескольких часов, проведенных с Google, я попытался запустить Qt Creator с командами этого терминала /opt/Qt5.7.0/Tools/QtCreator/bin/qtcreator -noload Welcome, и это сработало для меня.

Надеюсь, это кому-нибудь поможет. Извините за поздний ответ.

...