2015-04-09 40 views
5

Prima di tutto: questa domanda è già stata fatta un paio di volte e alcune risposte sono utili, ma nessuna fornisce una soluzione operativa. Ho iniziato provando il codice da this answer. Sorprendentemente, fa la sua cosa, ma c'è un grosso problema: l'unico modo per chiamare questo codice che mi viene in mente è il gestore SIGSEGV, e ha il suo stack - quindi non posso ottenere lo stack effettivo della mia app bloccata proprio come quella.Ottenere traccia dello stack su Android NDK

Quindi, ho provato a incorporare this answer. È leggermente migliore: produce il primo elemento dello stack (il metodo in cui si è verificato un arresto anomalo). Ma non c'è - nessun vero backtrace. Quindi, non appena si verifica un arresto anomalo all'interno di una libreria di terze parti (o di una libreria standard), questa informazione non ha senso.

Come posso migliorare ulteriormente il codice e ottenere infine la traccia di stack per la mia app povera in crash?

P. S. Testato su Android 4.0.3 e Android 5.0, finora il comportamento è lo stesso. Voglio supportare almeno 5.0 e le versioni precedenti recenti come 4.3-4.4.

+0

Giusto per essere chiari: stai provando a scrivere un gestore di crash in-app che cattura la traccia dello stack dopo un errore? Il gestore di segnale non ha il proprio stack a meno che non sia stato usato 'sigaltstack', sebbene sia possibile che lo svolgitore di stack non sappia come passare attraverso il frame dello stack di segnale. Qual è il tuo obiettivo finale? ACRA per l'NDK? – fadden

+0

@fadden: corretto, voglio ottenere una traccia dello stack post-morte. Sembrerebbe che il gestore del segnale abbia il proprio stack, che abbia origine in 'art :: handleFault' o qualcosa del genere (su 5.0). Cos'è l'ACRA? –

+0

Ho sentito dire che ART stava fornendo il proprio gestore di segnale che concatenato al gestore precedente; se questo è il caso, vedrai un comportamento diverso su 5.0 vs. 4.x con Dalvik. Questo è in cima al gestore di segnale installato dal sistema che alimenta il gestore di sistema debuggerd (che invia la traccia di stack al file di registro dopo un arresto anomalo nativo). Non pensavo che Android pthread lib usasse 'sigaltstack', ma non ho controllato da un po '. Dovresti scavare SP fuori dal frame del segnale e usarlo come punto di svolgimento, piuttosto che come SP corrente. – fadden

risposta

1

Hai provato la libreria coffeecatch?

È un rilevatore di segnali JNI che consente di trasformare i segnali SIGSEGV (+) nelle eccezioni java con backtrace misto jni/java. Funziona fino all'API-19, ma non ho ancora potuto testarlo su API> 19. Fornisce indirizzi di programma che possono essere passati a addr2line per ottenere i riferimenti finali a una fonte. modello

Codice:

#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)); 
    .... 
} 

Esempio della traccia:

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) parte l'analisi dello stack è stato:

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) 

E finalmente avere un humanoid- backtrace leggibile:

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

L'ho provato e non potevo fare quello che volevo. Ma non ho trovato il modo di ottenere lo stack (che si tratti di indirizzi o simboli). È nell'API Coffecatch? Hai qualche codice di esempio? Inoltre, gli indirizzi sono compatibili con 'dladdr'? –

+0

Vedere la mia risposta modificata sopra. + assicurati di utilizzare l'ultima versione di git, le vecchie versioni non funzionano con il moderno ndk. – Fvwm

+0

Grazie. Ho visto che può lanciare un'eccezione Java con una sorta di traccia stack, ma ho bisogno di quegli indirizzi nel blocco 'COFFEE_CATCH', quanto sarebbe difficile modificare l'origine coffecatch per accedere a quell'elenco di indirizzi? Inoltre, dover avvolgere ogni metodo in 'try/catch' è un grande ostacolo. Ho centinaia (più di 100, questo è sicuro) metodi nativi, e ognuno deve essere modificato. Un gestore globale del segnale è infinitamente più conveniente ... finché funziona. –

Problemi correlati