2015-04-09 8 views
5

Прежде всего: этот вопрос уже задан пару раз, и некоторые ответы полезны, но ни одно из них не дает рабочего решения. Я начал с кода this answer. Удивительно, но в этом есть огромная проблема: единственный способ вызвать этот код, о котором я могу думать, - это обработчик SIGSEGV, и у него есть собственный стек, поэтому я не могу получить фактический стек моего разбитого приложения, как что.Получение трассировки стека на Android NDK

Затем я попытался включить this answer. Он немного лучше - он дает первый элемент стека (метод, в котором произошел сбой). Но это не так. Поэтому, как только авария происходит внутри сторонней библиотеки (или стандартной библиотеки), эта информация не имеет смысла.

Как я могу улучшить код и, наконец, получить трассировку стека для моего плохого разбитого приложения?

P. S. Протестировано на Android 4.0.3 и Android 5.0, до сих пор поведение было таким же. Я хочу поддерживать как минимум 5.0 и последние предыдущие версии, такие как 4.3-4.4.

+0

Просто, чтобы быть ясным: вы пытаетесь написать обработчик сбоя в приложении, который захватывает трассировку стека после сбоя? Обработчик сигнала не имеет собственного стека, если не используется «sigaltstack', хотя возможно, что разматыватель стека не знает, как перешагнуть рамку стека сигналов. Какова ваша конечная цель? ACRA для NDK? – fadden

+0

@fadden: Правильно, я хочу получить посмертную трассировку стека. Казалось бы, обработчик сигнала имеет свой собственный стек, он происходит из 'art :: handleFault' или что-то вроде этого (в версии 5.0). Что такое ACRA? –

+0

Я слышал слух, что АРТ предоставляет свой собственный обработчик сигналов, привязанный к предыдущему обработчику; если это так, вы увидите другое поведение на 5.0 против 4.x с Dalvik. Это находится поверх установленного системой обработчика сигнала, который передает обработчик системы debuggerd (который выводит трассировку стека в файл журнала после нативного сбоя). Я не думал, что Android pthread lib использует 'sigaltstack', но я не проверял его некоторое время. Вам нужно выкопать SP из сигнального кадра и использовать его как вашу точку разворота, а не текущий SP. – fadden

ответ

1

Вы попробовали библиотеку coffeecatch?

Это змеевик сигнала JNI, который позволяет превращать сигналы SIGSEGV (+) в исключения java со смешанной обратной связью jni/java. Он работает до API-19, но у меня не было возможности проверить его на API> 19. Он предоставляет адреса программ, которые могут быть переданы в addr2line, чтобы получить окончательные ссылки на источники. Шаблон

Код:

#include "coffeejni.h" 
#include "coffeecatch.h" 

void MyClass::foo(JNIEnv *env, int arg1, int arg2) { 
    .... 
    int rc; 
    COFFEE_TRY_JNI(env, rc = crashInside(arg1, arg2)); 
    .... 
} 

Пример следа:

F/myapp (24535): "DESIGN ERROR": thread=t1 
F/myapp (24535): java.lang.Error: signal 11 (Address not mapped to object) at address 0xdeadbaad [at libc.so:0x18282] 
F/myapp (24535): at com.example.NativeSupport.nsc(Native Method) 
F/myapp (24535): at com.example.NativeSupport.nsc_quiet(NativeSupport.java:328) 
F/myapp (24535): at com.example.NativeSupport.loop(NativeSupport.java:287) 
F/myapp (24535): at com.example.NativeSupport.access$2(NativeSupport.java:274) 
F/myapp (24535): at com.example.NativeSupport$2.run(NativeSupport.java:124) 
F/myapp (24535): at java.lang.Thread.run(Thread.java:856) 
F/myapp (24535): Caused by: java.lang.Error: signal 11 (Address not mapped to object) at address 0xdeadbaad [at libc.so:0x18282] 
F/myapp (24535): at system.lib.libc_so.0x18282(Native Method) 
F/myapp (24535): at system.lib.libc_so.0xdc04(abort:0x4:0) 
F/myapp (24535): at data.data.example.lib.libexample_so.0xf147(Native Method) 
F/myapp (24535): at data.data.example.lib.libexample_so.0x12d1b(Native Method) 
F/myapp (24535): at data.data.example.lib.libexample_so.0x1347b(Native Method) 
F/myapp (24535): at data.data.example.lib.libexample_so.0x13969(Native Method) 
F/myapp (24535): at data.data.example.lib.libexample_so.0x13ab3(Native Method) 
F/myapp (24535): at data.data.example.lib.libexample_so.0x17a9b(Native Method) 
F/myapp (24535): at system.lib.libdvm_so.0x1f4b0(dvmPlatformInvoke:0x70:0) 
F/myapp (24535): at system.lib.libdvm_so.0x4dfa5(dvmCallJNIMethod(unsigned int const*, JValue*, Method const*, Thread*):0x164:0) 
F/myapp (24535): at system.lib.libdvm_so.0x28920(Native Method) 
F/myapp (24535): at system.lib.libdvm_so.0x2d0b0(dvmInterpret(Thread*, Method const*, JValue*):0xb4:0) 
F/myapp (24535): at system.lib.libdvm_so.0x5f599(dvmCallMethodV(Thread*, Method const*, Object*, bool, JValue*, std::__va_list):0x110:0) 
F/myapp (24535): at system.lib.libdvm_so.0x5f5c3(dvmCallMethod(Thread*, Method const*, Object*, JValue*, ...):0x14:0) 
F/myapp (24535): at system.lib.libdvm_so.0x549eb(Native Method) 
F/myapp (24535): at system.lib.libc_so.0x12dd0(__thread_entry:0x30:0) 
F/myapp (24535): at system.lib.libc_so.0x12534(pthread_create:0xac:0) 

Native (JNI) часть трассировки стека был:

F/myapp (24535): at data.data.example.lib.libexample_so.0xf147(Native Method) 
F/myapp (24535): at data.data.example.lib.libexample_so.0x12d1b(Native Method) 
F/myapp (24535): at data.data.example.lib.libexample_so.0x1347b(Native Method) 
F/myapp (24535): at data.data.example.lib.libexample_so.0x13969(Native Method) 
F/myapp (24535): at data.data.example.lib.libexample_so.0x13ab3(Native Method) 
F/myapp (24535): at data.data.example.lib.libexample_so.0x17a9b(Native Method) 

И, наконец, получить humanoid- читаемая обратная линия:

cd android-ndk/toolchains/arm-linux-androideabi-4.8/prebuilt/linux-x86_64/bin 
./arm-linux-androideabi-addr2line -e /home/joe/myproj/obj/local/armeabi-v7a/libexample.so 0xf147 0x12d1b 0x1347b 0x13969 0x13ab3 0x17a9b 
+1

Я пробовал и не мог делать то, что хочу. Но я также не нашел способ получить стек (будь то адреса или символы). Это в API Coffecatch? У вас есть код примера? Также являются ли адреса совместимыми с 'dladdr'? –

+0

См. Мой измененный ответ выше. + убедитесь, что вы используете последнюю версию git, старые версии не работают с современными ndk. – Fvwm

+0

Спасибо. Я видел, что он может вызывать исключение Java с какой-то трассировкой стека, но мне нужны эти адреса в блоке 'COFFEE_CATCH', насколько сложно было бы изменить источник coffecatch, чтобы получить доступ к этому списку адресов? Кроме того, использование каждого метода в 'try/catch' является большим препятствием. У меня есть сотни (более 100, это точно) собственные методы, и каждый из них должен быть изменен. Глобальный обработчик сигналов бесконечно более удобен ... пока он работает. –

Смежные вопросы