2015-04-09 9 views
5

Zunächst einmal: diese Frage wurde bereits ein paar Mal gestellt, und einige Antworten sind nützlich, aber keine bieten eine funktionierende Lösung. Ich fing an, indem ich den Code von this answer versuchte. Überraschenderweise tut es sein Ding, aber es gibt ein riesiges Problem: die einzige Art, diesen Code zu nennen, ist SIGSEGV Handler, und es hat seinen eigenen Stapel - daher kann ich nicht den tatsächlichen Stapel meiner abgestürzten App genau so bekommen Das.Get Stack-Spur auf Android NDK

Dann habe ich versucht, this answer zu integrieren. Es ist etwas besser - es liefert das erste Element des Stapels (die Methode, bei der ein Absturz aufgetreten ist). Aber das ist in - kein tatsächliches Backtrace. Sobald der Absturz in einer Bibliothek eines Drittanbieters (oder einer Standardbibliothek) auftritt, ist diese Information bedeutungslos.

Wie kann ich den Code weiter verbessern und schließlich den Stack-Trace für meine schlechte abgestürzte App bekommen?

P.S. Getestet auf Android 4.0.3 und Android 5.0, bis jetzt ist das Verhalten das gleiche. Ich möchte mindestens 5.0 und die letzten früheren Versionen wie 4.3-4.4 unterstützen.

+0

Nur um es klarzustellen: Sie versuchen, einen In-App-Crash-Handler zu schreiben, der die Stack-Trace nach einem Fehler erfasst? Der Signal-Handler hat keinen eigenen Stapel, es sei denn, "sigaltstack" wurde verwendet, obwohl es möglich ist, dass der Stapel-Abwickler nicht weiß, wie er über den Signalstapelrahmen tritt. Was ist dein ultimatives Ziel? ACRA für den NDK? – fadden

+0

@fadden: richtig, ich möchte eine Post-Mortem-Stack-Spur bekommen. Es würde erscheinen, da der Signalhandler seinen eigenen Stapel hat, er stammt von 'art :: handleFault' oder etwas ähnlichem (auf 5.0). Was ist ACRA? –

+0

Ich hörte ein Gerücht, dass ART einen eigenen Signal-Handler zur Verfügung stellte, der an den vorherigen Handler angekettet war; Wenn das der Fall ist, werden Sie ein unterschiedliches Verhalten auf 5.0 gegenüber 4.x mit Dalvik sehen. Dies liegt über dem systeminstallierten Signalhandler, der den debuggerd-Systemhandler einspeist (der den Stack-Trace nach einem systemeigenen Absturz an die Protokolldatei ausgibt). Ich dachte nicht, dass die Android-pthread-Bibliothek 'sigaltstack' verwendet, aber ich habe mich noch nicht eingecheckt. Sie müssten SP aus dem Signalrahmen ausgraben und diesen als Ihren Abwicklungspunkt anstelle des aktuellen SP verwenden. – fadden

Antwort

1

Haben Sie die Bibliothek coffeecatch getestet?

Es ist ein JNI-Signal-Catcher, der ermöglicht, SIGSEGV (+) - Signale in die Java-Ausnahmen mit gemischten jni/Java-Backtrace zu drehen. Es funktioniert bis API-19, aber ich hatte noch keine Chance es auf API> 19 zu testen. Es stellt Programmadressen zur Verfügung, die an addr2line übergeben werden können, um die endgültigen Verweise auf eine Quelle zu erhalten.

-Code-Vorlage:

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

Beispiel der Spur:

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) Teil der Stack-Trace war:

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) 

Und endlich ein humanoid- lesbare Rückverfolgung:

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

Ich habe es versucht und konnte nicht tun, was ich will. Aber ich habe auch keinen Weg gefunden, den Stack zu bekommen (seien es Adressen oder Symbole). Ist es in der Coffecatch API? Hast du einen Beispielcode? Sind die Adressen auch mit 'dladdr' kompatibel? –

+0

Siehe meine geänderte Antwort oben. + sicher sein, dass Sie die neueste Version von Git verwenden, alte Versionen funktioniert nicht mit modernen ndk. – Fvwm

+0

Danke. Ich habe gesehen, dass es eine Java-Ausnahme mit einer Art Stack-Trace auslösen kann, aber ich brauche diese Adressen im 'COFFEE_CATCH'-Block, wie schwer wäre es, die coffecatch-Quelle zu modifizieren, um Zugang zu dieser Liste von Adressen zu erhalten? Auch jede Methode in "try/catch" zu wickeln, ist ein großes Hindernis. Ich habe Hunderte (über 100, das ist sicher) native Methoden, und jede muss geändert werden. Ein globaler Signal-Handler ist unendlich bequemer ... solange er funktioniert. –