Стеки останавливаются перед тем, как перейти к моему коду (на Android с помощью NDK)

Я развиваюсь на Android 2.3.x, используя NDK r5b. Иногда мой код падает, и я хотел бы знать, где. Я уже знаю, как получить соответствующую строку в моем приложении, когда у меня есть указатель (т.е. Из трассировки стека Android.)

Однако часто я вижу бесполезные трассировки стека (полный тракт стека):

     #00  pc 0006561a  /system/lib/egl/libGLESv2_adreno200.so
     #01  pc 0006b900  /system/lib/egl/libGLESv2_adreno200.so
     #02  pc 0005aac8  /system/lib/egl/libGLESv2_adreno200.so
     #03  pc 0001687a  /system/lib/egl/libGLESv1_CM_adreno200.so
     #04  pc 000096ce  /system/lib/egl/libGLESv1_CM_adreno200.so

или это:

(gdb) bt
#0  0xafd0c51c in epoll_wait () from /Volumes/SecureCode/webos/rta/android/obj/local/armeabi/libc.so
#1  0xa81216a6 in ?? ()

которые даже не упоминают мой код вообще.

Есть ли вообще способ улучшить трассировку стека? Почему некоторые функции библиотеки "непрозрачны" в том смысле, что они не позволяют обратному каналу "видеть" вызывающую функцию, вызывая остановку в трассировке стека?

Насколько я могу судить, единственным способом отладки такой проблемы является использование журнала в каждой точке программы и/или переход по каждой строке с помощью gdb.

Доступны ли ПЗУ с отладочными версиями этих Android-библиотек вместо исполняемых файлов, и это поможет? (Я использую один телефон исключительно для разработки, поэтому я не заинтересован в сохранении полной функциональности.) ( Фактически, я заметил, что путь к libc.so в вышеуказанной трассе стека gdb находится внутри мой каталог приложений. Могу ли я просто скомпоновать его с другим (отладочным) libc.so, и это поможет?)

Последнее, что может помочь: в предыдущей трассировке стека из logcat (первая) моя библиотека упоминается в дампе необработанного стека:

stack:
  ...
  ...
  4471cb88  00000028  
  4471cb8c  afd4649c  
  4471cb90  80b4eb71  /data/data/com.audia.dev.rta/lib/librta.so
  4471cb94  00299180  
  ...
  ...

но это не указатель функции. Что это может быть, и может ли это быть полезной после того, как приложение разбилось? Я думаю, вероятно, нет, если это указатель кучи или что-то в этом роде.

Ответ 1

Есть ли вообще способ получить лучшие трассировки стека, чем это?

Насколько я знаю, вы должны сами создать и написать образ Android. Он позволяет вам иметь все полные символы Android (исполняемые файлы и общие библиотеки), кроме проприетарных разделяемых библиотек.

Также он обеспечивает использование символов с помощью gdb.

$ adb shell setprop debug.db.uid 32767
$ adb forward tcp:5039 tcp:5039

/*
 program terminated and debuggerd caught exception like the following.
 Use the PID number for gdbclient 3rd parameter.
 I/DEBUG   ( 2154): ******************************************************** 
 I/DEBUG   ( 2154): * Process 2508 has been suspended while crashing.  To
 I/DEBUG   ( 2154): * attach gdbserver for a gdb connection on port 5039:
 I/DEBUG   ( 2154): *
 I/DEBUG   ( 2154): *     adb shell gdbserver :5039 --attach 2508 &
 I/DEBUG   ( 2154): *
 I/DEBUG   ( 2154): * Press HOME key to let the process continue crashing.
 I/DEBUG   ( 2154): ********************************************************)
*/

$ gdbclient "" "" 2508

Редакция:

Вы можете использовать ndk-gdb вместо команды gdbclient. Укажите файлы символов для разделяемых библиотек.

(gdb) set solib-search-path (ANDROID_SOURCE_PATH)/out/target/product/(PRODUCT_NAME)/symbols/system/lib

EDITED 2:

Если вам не нужны символы системных разделяемых библиотек Android, просто adb вытащите общие библиотеки и установите для него путь поиска sollib.

$ adb pull /system/lib lib

$ ndk-gdb
...
(gdb) set solib-search-path lib

Ответ 2

Пара примечаний:

  • В некоторых случаях трассировка стека может быть повреждена, потому что ваш стек был частично поврежден. Вряд ли.
  • Какую ОС вы используете? Gingerbread (Android 2.3) лучше значительно с точки зрения трассировки стека. Если вы не используете Android 2.3, найдите Android 2.3 для своего телефона где-нибудь или получите дешевый телефон для разработки, который работает 2,3.
  • Вы видели Onur script? Он работал очень хорошо для меня, даже на телефонах Android 2.2.
  • Надеюсь, что fadden читает это, я уверен, что у него есть ответ, который гораздо полезнее, чем мой.

Ответ 3

Обратите внимание на следующий вопрос: Как сгенерировать stacktrace при сбое моего приложения gcc С++

Мы сделали то же самое с нашим Android-приложением: мы написали собственный обработчик сигналов, обработали сигналы 7 (sigbus) и 11 (sigsegv) и распечатали стопку из обработчика. Однако мы не использовали функцию backtrace(), но вручную раскрутили стек...

Объединяя первые два ответа, вы сможете написать свой собственный обработчик сигнала, чтобы сбрасывать трассировку стека. Эта статья также может помочь вам: http://www.ibm.com/developerworks/power/library/l-sigdebug/index.html. Имейте в виду, что извлечение содержимого регистра зависит от архитектуры, поэтому вы должны подменять структуры, используемые в вышеуказанных кодах, на те, которые указаны в android (зависит от процессора ARM). Например, я должен был вставить в источник Android для "struct ucontext".

Когда у вас есть трассировка стека, запустите script на выходе, который разрешит символы с помощью addr2line и вашего незастроенного исполняемого файла.

Ответ 4

Извините, что наполнил свой вопрос ответами, но я обнаружил, что интеграция Google Breakpad - отличный способ получить хорошие трассировки стека/отчеты о сбоях. Легко написать обработчик сигнала, который вызывает Breakpad, и это заботится обо всем; нам просто нужно загрузить отчеты на наш сервер. Мы также интегрировали процесс вызова stackwalk.sh в нашу систему сборки. Это заняло определенную работу, но в целом это идеально подходит для получения хороших отчетов о сбоях в работе на Android.

Этот ответ содержит некоторые сведения о написании обработчика сигналов; остальная часть кода, который вам нужен, находится на сайте Google Breakpad под вики.

Ответ 5

Я получил ответ на этот вопрос для некоторых трасс стека. (Из внешнего вида этого вопроса, который может быть все, что я получаю.) Это те, которые заканчиваются с адресом lr (link register). См. Мой другой вопрос/ответ.