Только вопросительные знаки в обратном следе, сообщенные GDB на ARM - PullRequest
7 голосов
/ 09 декабря 2011

Я пытаюсь отладить программное обеспечение с помощью gdbserver на ARM, чтобы получить обратную информацию о сбое.К сожалению, я получаю только вопросительные знаки.Везде, где я читал, эта проблема просто связана с отсутствием символов, но символы не удаляются из моих библиотек.

Если я пытаюсь использовать команду file для загрузки символов в клиент, я получаю:

reading symbols from <path>/libQtWebKit.so.4.7.2...(no debugging symbols found)...done.

и затем, когда происходит сбой:

Program received signal SIGSEGV, Segmentation fault.
0x00000000 in ?? ()
(gdb) bt
#0  0x00000000 in ?? ()
#1  0x4bf38b88 in ?? ()
Backtrace stopped: previous frame identical to this frame (corrupt stack?)

Мои библиотеки скомпилированы в выпуске, но символы на самом деле присутствуют.С нм я могу найти их.Почему я получаю только вопросительные знаки?Только потому, что библиотеки скомпилированы с оптимизацией?Разве нельзя отлаживать библиотеки в режиме выпуска?

Ответы [ 2 ]

2 голосов
/ 09 декабря 2011

Примечание corrupt stack, вероятно, ваша проблема. Похоже, адрес возврата или запись виртуальной таблицы или что-то было перезаписано нулями, а затем управление было передано туда. Даже если у вас есть доступные символы, эти адреса не указывают на действительные символы. Отсюда и ошибка.

Я не завидую твоей задаче. Это одни из самых сложных ошибок, которые можно отследить, и они могут даже перемещаться или временно исчезать, когда вы вносите изменения в код, чтобы попытаться их поймать. Лучшей вашей ставкой обычно является что-то вроде git bisect или эквивалент VCS, чтобы найти коммит, который его ввел. Надеюсь, это не так сложно воспроизвести.

1 голос
/ 09 декабря 2011

Одна хитрость, которую вы иногда можете использовать, когда получаете проблему «SEGV at address 0», - это вручную вставить адрес возврата с вершины стека в компьютер и попытаться выполнить оттуда трассировку стека.Это предполагает, что вы получили адрес 0, выполнив косвенный вызов через указатель NULL, который является наиболее распространенным способом получения адреса 0.

Теперь я не слишком знаком с ARM, но на x86ПК, вы должны сделать:

(gdb) set $eip = *(void **)$esp
(gdb) set $esp = $esp + 4

и затем сделать еще одну обратную трассировку, чтобы выяснить, где вы на самом деле.

Если вы можете выяснить соглашение о вызовах, используемое для ARM вашим компилятором, выдолжно быть в состоянии сделать что-то подобное.

...