Die folgenden Abschnitte enthalten häufige Arten von systemeigenen Abstürzen, eine Analyse eines Beispielabsturzspeicherauszugs und eine Erörterung von Tombstones. Jeder Absturztyp enthält eine Beispiel- debuggerd
-Ausgabe mit hervorgehobenen Schlüsselhinweisen, die Ihnen helfen, die spezifische Art des Absturzes zu unterscheiden.
Abbrechen
Abbrüche sind interessant, weil sie absichtlich sind. Es gibt viele verschiedene Möglichkeiten zum Abbrechen (einschließlich des Aufrufs von abort(3)
, des Fehlschlagens eines assert(3)
, der Verwendung eines der Android-spezifischen schwerwiegenden Protokollierungstypen), aber alle beinhalten den Aufruf von abort
. Ein Aufruf zum Abbrechen signalisiert dem aufrufenden Thread SIGABRT, sodass ein Frame, der „ abort
“ in libc.so
plus SIGABRT anzeigt, die Dinge sind, nach denen in der debuggerd
-Ausgabe gesucht werden muss, um diesen Fall zu erkennen.
Es kann eine explizite "Abbruchmeldung"-Zeile geben. Sie sollten auch in der logcat
Ausgabe nachsehen, was dieser Thread protokolliert hat, bevor er sich absichtlich selbst beendet, da abort(3)
im Gegensatz zu assert(3)
oder schwerwiegenden Protokollierungsfunktionen auf hoher Ebene keine Nachricht akzeptiert.
Aktuelle Versionen von Android integrieren den tgkill(2)
, sodass ihre Stacks am einfachsten zu lesen sind, mit dem Aufruf von abort(3) ganz oben:
pid: 4637, tid: 4637, name: crasher >>> crasher <<< signal 6 (SIGABRT), code -6 (SI_TKILL), fault addr -------- Abort message: 'some_file.c:123: some_function: assertion "false" failed' r0 00000000 r1 0000121d r2 00000006 r3 00000008 r4 0000121d r5 0000121d r6 ffb44a1c r7 0000010c r8 00000000 r9 00000000 r10 00000000 r11 00000000 ip ffb44c20 sp ffb44a08 lr eace2b0b pc eace2b16 backtrace: #00 pc 0001cb16 /system/lib/libc.so (abort+57) #01 pc 0001cd8f /system/lib/libc.so (__assert2+22) #02 pc 00001531 /system/bin/crasher (do_action+764) #03 pc 00002301 /system/bin/crasher (main+68) #04 pc 0008a809 /system/lib/libc.so (__libc_init+48) #05 pc 00001097 /system/bin/crasher (_start_main+38)
Ältere Android-Versionen folgten einem verschlungenen Pfad zwischen dem ursprünglichen Abbruchaufruf (Frame 4 hier) und dem eigentlichen Senden des Signals (Frame 0 hier). Dies galt insbesondere für 32-Bit-ARM, das __libc_android_abort
(Frame 3 hier) zur Folge von raise
/ pthread_kill
/ tgkill
der anderen Plattformen hinzufügte:
pid: 1656, tid: 1656, name: crasher >>> crasher <<< signal 6 (SIGABRT), code -6 (SI_TKILL), fault addr -------- Abort message: 'some_file.c:123: some_function: assertion "false" failed' r0 00000000 r1 00000678 r2 00000006 r3 f70b6dc8 r4 f70b6dd0 r5 f70b6d80 r6 00000002 r7 0000010c r8 ffffffed r9 00000000 sl 00000000 fp ff96ae1c ip 00000006 sp ff96ad18 lr f700ced5 pc f700dc98 cpsr 400b0010 backtrace: #00 pc 00042c98 /system/lib/libc.so (tgkill+12) #01 pc 00041ed1 /system/lib/libc.so (pthread_kill+32) #02 pc 0001bb87 /system/lib/libc.so (raise+10) #03 pc 00018cad /system/lib/libc.so (__libc_android_abort+34) #04 pc 000168e8 /system/lib/libc.so (abort+4) #05 pc 0001a78f /system/lib/libc.so (__libc_fatal+16) #06 pc 00018d35 /system/lib/libc.so (__assert2+20) #07 pc 00000f21 /system/xbin/crasher #08 pc 00016795 /system/lib/libc.so (__libc_init+44) #09 pc 00000abc /system/xbin/crasher
Sie können einen Fall dieser Art von Absturz mit crasher abort
reproduzieren.
Reine Nullzeiger-Dereferenzierung
Dies ist der klassische native Absturz, und obwohl es sich nur um einen Sonderfall des nächsten Absturztyps handelt, ist er gesondert zu erwähnen, da er normalerweise am wenigsten Nachdenken erfordert.
Obwohl sich die abstürzende Funktion im folgenden Beispiel in libc.so
befindet, können Sie schlussfolgern, dass strlen(3)
mit einem Nullzeiger aufgerufen wurde, da die Zeichenfolgenfunktionen nur mit den ihnen übergebenen Zeigern arbeiten; und dieser Absturz sollte direkt an den Autor des aufrufenden Codes gehen. In diesem Fall ist Rahmen Nr. 01 der schlechte Anrufer.
pid: 25326, tid: 25326, name: crasher >>> crasher <<< signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0x0 r0 00000000 r1 00000000 r2 00004c00 r3 00000000 r4 ab088071 r5 fff92b34 r6 00000002 r7 fff92b40 r8 00000000 r9 00000000 sl 00000000 fp fff92b2c ip ab08cfc4 sp fff92a08 lr ab087a93 pc efb78988 cpsr 600d0030 backtrace: #00 pc 00019988 /system/lib/libc.so (strlen+71) #01 pc 00001a8f /system/xbin/crasher (strlen_null+22) #02 pc 000017cd /system/xbin/crasher (do_action+948) #03 pc 000020d5 /system/xbin/crasher (main+100) #04 pc 000177a1 /system/lib/libc.so (__libc_init+48) #05 pc 000010e4 /system/xbin/crasher (_start+96)
Sie können einen solchen Absturz mit crasher strlen-NULL
.
Nullzeiger-Dereferenzierung bei niedrigen Adressen
In vielen Fällen ist die Fehleradresse nicht 0, sondern eine andere niedrige Zahl. Insbesondere zwei- oder dreistellige Adressen sind sehr verbreitet, während eine sechsstellige Adresse mit ziemlicher Sicherheit keine Nullzeiger-Dereferenzierung ist – das würde einen Offset von 1 MiB erfordern. Dies tritt normalerweise auf, wenn Sie Code haben, der einen Nullzeiger dereferenziert, als wäre es eine gültige Struktur. Übliche Funktionen sind fprintf(3)
(oder jede andere Funktion, die eine FILE* nimmt) und readdir(3)
, da der Code oft nicht überprüft, ob der fopen(3)
- oder opendir(3)
tatsächlich zuerst erfolgreich war.
Hier ist ein Beispiel für readdir
:
pid: 25405, tid: 25405, name: crasher >>> crasher <<< signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0xc r0 0000000c r1 00000000 r2 00000000 r3 3d5f0000 r4 00000000 r5 0000000c r6 00000002 r7 ff8618f0 r8 00000000 r9 00000000 sl 00000000 fp ff8618dc ip edaa6834 sp ff8617a8 lr eda34a1f pc eda618f6 cpsr 600d0030 backtrace: #00 pc 000478f6 /system/lib/libc.so (pthread_mutex_lock+1) #01 pc 0001aa1b /system/lib/libc.so (readdir+10) #02 pc 00001b35 /system/xbin/crasher (readdir_null+20) #03 pc 00001815 /system/xbin/crasher (do_action+976) #04 pc 000021e5 /system/xbin/crasher (main+100) #05 pc 000177a1 /system/lib/libc.so (__libc_init+48) #06 pc 00001110 /system/xbin/crasher (_start+96)
Hier ist die direkte Ursache des Absturzes, dass pthread_mutex_lock(3)
versucht hat, auf die Adresse 0xc (Frame 0) zuzugreifen. Aber als erstes dereferenziert pthread_mutex_lock
das state
Element von pthread_mutex_t*
, das ihm gegeben wurde. Wenn Sie sich die Quelle ansehen, können Sie sehen, dass sich das Element am Offset 0 in der Struktur befindet, was Ihnen sagt, dass pthread_mutex_lock
den ungültigen Zeiger 0xc erhalten hat. Aus Frame 1 können Sie sehen, dass ihm dieser Zeiger von readdir
gegeben wurde, wodurch das Feld mutex_
aus dem angegebenen DIR*
extrahiert wird. Wenn Sie sich diese Struktur ansehen, können Sie sehen, dass mutex_
am Offset sizeof(int) + sizeof(size_t) + sizeof(dirent*)
in struct DIR
liegt, was auf einem 32-Bit-Gerät 4 + 4 + 4 = 12 = 0xc ist. Sie haben also den Fehler gefunden: readdir
wurde vom Aufrufer ein Nullzeiger übergeben. An dieser Stelle können Sie den Stack in das Stack-Tool einfügen, um herauszufinden, wo in Logcat dies passiert ist.
struct DIR { int fd_; size_t available_bytes_; dirent* next_; pthread_mutex_t mutex_; dirent buff_[15]; long current_pos_; };
In den meisten Fällen können Sie diese Analyse sogar überspringen. Eine ausreichend niedrige Fehleradresse bedeutet normalerweise, dass Sie einfach alle libc.so
Frames im Stack überspringen und den aufrufenden Code direkt beschuldigen können. Aber nicht immer, und so würden Sie einen überzeugenden Fall präsentieren.
Sie können Fälle dieser Art von Absturz mit crasher fprintf-NULL
oder crasher readdir-NULL
.
FORTIFY-Fehler
Ein FORTIFY-Fehler ist ein Sonderfall eines Abbruchs, der auftritt, wenn die C-Bibliothek ein Problem erkennt, das zu einer Sicherheitslücke führen könnte. Viele C-Bibliotheksfunktionen sind verstärkt ; Sie nehmen ein zusätzliches Argument, das ihnen sagt, wie groß ein Puffer tatsächlich ist, und prüfen zur Laufzeit, ob die Operation, die Sie ausführen möchten, tatsächlich passt. Hier ist ein Beispiel, in dem der Code versucht, read(fd, buf, 32)
, der eigentlich nur 10 Bytes lang ist ...
pid: 25579, tid: 25579, name: crasher >>> crasher <<< signal 6 (SIGABRT), code -6 (SI_TKILL), fault addr -------- Abort message: 'FORTIFY: read: prevented 32-byte write into 10-byte buffer' r0 00000000 r1 000063eb r2 00000006 r3 00000008 r4 ff96f350 r5 000063eb r6 000063eb r7 0000010c r8 00000000 r9 00000000 sl 00000000 fp ff96f49c ip 00000000 sp ff96f340 lr ee83ece3 pc ee86ef0c cpsr 000d0010 backtrace: #00 pc 00049f0c /system/lib/libc.so (tgkill+12) #01 pc 00019cdf /system/lib/libc.so (abort+50) #02 pc 0001e197 /system/lib/libc.so (__fortify_fatal+30) #03 pc 0001baf9 /system/lib/libc.so (__read_chk+48) #04 pc 0000165b /system/xbin/crasher (do_action+534) #05 pc 000021e5 /system/xbin/crasher (main+100) #06 pc 000177a1 /system/lib/libc.so (__libc_init+48) #07 pc 00001110 /system/xbin/crasher (_start+96)
Sie können einen Fall dieser Art von Absturz mit crasher fortify
reproduzieren.
Stapelbeschädigung von -fstack-protector erkannt
Die Option -fstack-protector
des Compilers fügt Prüfungen in Funktionen mit On-Stack-Puffer ein, um vor Pufferüberläufen zu schützen. Diese Option ist standardmäßig für Plattformcode aktiviert, nicht jedoch für Apps. Wenn diese Option aktiviert ist, fügt der Compiler Anweisungen zum Funktionsprolog hinzu, um einen zufälligen Wert direkt nach dem letzten lokalen Wert auf dem Stapel zu schreiben, und zum Funktionsepilog, um ihn zurückzulesen und zu überprüfen, ob er nicht geändert wurde. Wenn sich dieser Wert geändert hat, wurde er durch einen Pufferüberlauf überschrieben, sodass der Epilog __stack_chk_fail
, um eine Nachricht zu protokollieren und abzubrechen.
pid: 26717, tid: 26717, name: crasher >>> crasher <<< signal 6 (SIGABRT), code -6 (SI_TKILL), fault addr -------- Abort message: 'stack corruption detected' r0 00000000 r1 0000685d r2 00000006 r3 00000008 r4 ffd516d8 r5 0000685d r6 0000685d r7 0000010c r8 00000000 r9 00000000 sl 00000000 fp ffd518bc ip 00000000 sp ffd516c8 lr ee63ece3 pc ee66ef0c cpsr 000e0010 backtrace: #00 pc 00049f0c /system/lib/libc.so (tgkill+12) #01 pc 00019cdf /system/lib/libc.so (abort+50) #02 pc 0001e07d /system/lib/libc.so (__libc_fatal+24) #03 pc 0004863f /system/lib/libc.so (__stack_chk_fail+6) #04 pc 000013ed /system/xbin/crasher (smash_stack+76) #05 pc 00001591 /system/xbin/crasher (do_action+280) #06 pc 00002219 /system/xbin/crasher (main+100) #07 pc 000177a1 /system/lib/libc.so (__libc_init+48) #08 pc 00001144 /system/xbin/crasher (_start+96)
Sie können dies von anderen Abbrucharten durch das Vorhandensein von __stack_chk_fail
im Backtrace und der spezifischen Abbruchmeldung unterscheiden.
Sie können einen solchen Absturz mit crasher smash-stack
reproduzieren.
Seccomp SIGSYS von einem unzulässigen Systemaufruf
Das seccomp -System (insbesondere seccomp-bpf) beschränkt den Zugriff auf Systemaufrufe. Weitere Informationen zu seccomp für Plattformentwickler finden Sie im Blogbeitrag Seccomp-Filter in Android O . Ein Thread, der einen eingeschränkten Systemaufruf aufruft, erhält ein SIGSYS-Signal mit dem Code SYS_SECCOMP. Die Systemrufnummer wird zusammen mit der Architektur in der Ursachenzeile angezeigt. Es ist wichtig zu beachten, dass die Systemaufrufnummern zwischen den Architekturen variieren. Beispielsweise ist der readlinkat(2)
die Nummer 305 auf x86, aber 267 auf x86-64. Die Rufnummer ist sowohl auf arm als auch auf arm64 wieder unterschiedlich. Da die Systemaufrufnummern zwischen den Architekturen variieren, ist es normalerweise einfacher, den Stack-Trace zu verwenden, um herauszufinden, welcher Systemaufruf nicht zugelassen wurde, anstatt nach der Systemaufrufnummer in den Headern zu suchen.
pid: 11046, tid: 11046, name: crasher >>> crasher <<< signal 31 (SIGSYS), code 1 (SYS_SECCOMP), fault addr -------- Cause: seccomp prevented call to disallowed arm system call 99999 r0 cfda0444 r1 00000014 r2 40000000 r3 00000000 r4 00000000 r5 00000000 r6 00000000 r7 0001869f r8 00000000 r9 00000000 sl 00000000 fp fffefa58 ip fffef898 sp fffef888 lr 00401997 pc f74f3658 cpsr 600f0010 backtrace: #00 pc 00019658 /system/lib/libc.so (syscall+32) #01 pc 00001993 /system/bin/crasher (do_action+1474) #02 pc 00002699 /system/bin/crasher (main+68) #03 pc 0007c60d /system/lib/libc.so (__libc_init+48) #04 pc 000011b0 /system/bin/crasher (_start_main+72)
Sie können unzulässige Systemaufrufe von anderen Abstürzen durch das Vorhandensein von SYS_SECCOMP
auf der Signalleitung und der Beschreibung auf der Ursachenleitung unterscheiden.
Sie können einen solchen Absturz mit crasher seccomp
.
Nur-Ausführen-Speicherverletzung (nur Android 10)
Nur für arm64 in Android 10 wurden ausführbare Segmente von Binärdateien und Bibliotheken in den Arbeitsspeicher nur zum Ausführen (nicht lesbar) als Härtungstechnik gegen Code-Wiederverwendungsangriffe abgebildet. Diese Minderung interagierte schlecht mit anderen Minderungen und wurde später entfernt.
Code unlesbar zu machen führt dazu, dass beabsichtigte und unbeabsichtigte Lesevorgänge in Speichersegmente, die als Nur-Ausführung gekennzeichnet sind, ein SIGSEGV
mit dem Code SEGV_ACCERR
. Dies kann auf einen Fehler, eine Schwachstelle, mit Code gemischte Daten (z. B. einen Literal-Pool) oder eine absichtliche Speicherintrospektion zurückzuführen sein.
Der Compiler geht davon aus, dass Code und Daten nicht vermischt sind, aber bei der handschriftlichen Assemblierung können Probleme auftreten. In vielen Fällen können diese behoben werden, indem die Konstanten einfach in einen .data
Abschnitt verschoben werden. Wenn eine Code-Introspektion für ausführbare Codeabschnitte unbedingt erforderlich ist, sollte mprotect(2)
zuerst aufgerufen werden, um den Code als lesbar zu markieren, und dann erneut, um ihn nach Abschluss der Operation als unlesbar zu markieren.
pid: 2938, tid: 2940, name: crasher64 >>> crasher64 <<< signal 11 (SIGSEGV), code 2 (SEGV_ACCERR), fault addr 0x5f2ced24a8 Cause: execute-only (no-read) memory access error; likely due to data in .text. x0 0000000000000000 x1 0000005f2cecf21f x2 0000000000000078 x3 0000000000000053 x4 0000000000000074 x5 8000000000000000 x6 ff71646772607162 x7 00000020dcf0d16c x8 0000005f2ced24a8 x9 000000781251c55e x10 0000000000000000 x11 0000000000000000 x12 0000000000000014 x13 ffffffffffffffff x14 0000000000000002 x15 ffffffffffffffff x16 0000005f2ced52f0 x17 00000078125c0ed8 x18 0000007810e8e000 x19 00000078119fbd50 x20 00000078125d6020 x21 00000078119fbd50 x22 00000b7a00000b7a x23 00000078119fbdd8 x24 00000078119fbd50 x25 00000078119fbd50 x26 00000078119fc018 x27 00000078128ea020 x28 00000078119fc020 x29 00000078119fbcb0 sp 00000078119fba40 lr 0000005f2ced1b94 pc 0000005f2ced1ba4 backtrace: #00 pc 0000000000003ba4 /system/bin/crasher64 (do_action+2348) #01 pc 0000000000003234 /system/bin/crasher64 (thread_callback+44) #02 pc 00000000000e2044 /apex/com.android.runtime/lib64/bionic/libc.so (__pthread_start(void*)+36) #03 pc 0000000000083de0 /apex/com.android.runtime/lib64/bionic/libc.so (__start_thread+64)
Anhand der Ursachenzeile können Sie Nur-Ausführen-Speicherverletzungen von anderen Abstürzen unterscheiden.
Sie können einen solchen Absturz mit crasher xom
.
Fehler von fdsan erkannt
Der fdsan File Descriptor Sanitizer von Android hilft dabei, häufige Fehler mit Dateideskriptoren wie use-after-close und double-close zu erkennen. Weitere Einzelheiten zum Debuggen (und Vermeiden) dieser Fehlerklasse finden Sie in der fdsan-Dokumentation .
pid: 32315, tid: 32315, name: crasher64 >>> crasher64 <<< signal 35 (), code -1 (SI_QUEUE), fault addr -------- Abort message: 'attempted to close file descriptor 3, expected to be unowned, actually owned by FILE* 0x7d8e413018' x0 0000000000000000 x1 0000000000007e3b x2 0000000000000023 x3 0000007fe7300bb0 x4 3033313465386437 x5 3033313465386437 x6 3033313465386437 x7 3831303331346538 x8 00000000000000f0 x9 0000000000000000 x10 0000000000000059 x11 0000000000000034 x12 0000007d8ebc3a49 x13 0000007fe730077a x14 0000007fe730077a x15 0000000000000000 x16 0000007d8ec9a7b8 x17 0000007d8ec779f0 x18 0000007d8f29c000 x19 0000000000007e3b x20 0000000000007e3b x21 0000007d8f023020 x22 0000007d8f3b58dc x23 0000000000000001 x24 0000007fe73009a0 x25 0000007fe73008e0 x26 0000007fe7300ca0 x27 0000000000000000 x28 0000000000000000 x29 0000007fe7300c90 sp 0000007fe7300860 lr 0000007d8ec2f22c pc 0000007d8ec2f250 backtrace: #00 pc 0000000000088250 /bionic/lib64/libc.so (fdsan_error(char const*, ...)+384) #01 pc 0000000000088060 /bionic/lib64/libc.so (android_fdsan_close_with_tag+632) #02 pc 00000000000887e8 /bionic/lib64/libc.so (close+16) #03 pc 000000000000379c /system/bin/crasher64 (do_action+1316) #04 pc 00000000000049c8 /system/bin/crasher64 (main+96) #05 pc 000000000008021c /bionic/lib64/libc.so (_start_main)
Sie können dies von anderen Abbrucharten durch das Vorhandensein von fdsan_error
im Backtrace und der spezifischen Abbruchmeldung unterscheiden.
Sie können einen solchen Absturz mit crasher fdsan_file
oder crasher fdsan_dir
fdsan_dir reproduzieren.
Untersuchung von Crash-Dumps
Wenn Sie gerade keinen bestimmten Absturz untersuchen, enthält die Plattformquelle ein Tool zum Testen von debuggerd
namens crasher. Wenn Sie in system/core/debuggerd/
mm
eingeben, erhalten Sie sowohl einen crasher
als auch einen crasher64
auf Ihrem Pfad (letzteres ermöglicht es Ihnen, 64-Bit-Abstürze zu testen). Crasher kann basierend auf den von Ihnen bereitgestellten Befehlszeilenargumenten auf viele interessante Arten abstürzen. Verwenden Sie crasher --help
, um die derzeit unterstützte Auswahl anzuzeigen.
Um die verschiedenen Teile in einem Crash-Dump vorzustellen, lassen Sie uns dieses Beispiel-Crash-Dump durcharbeiten:
*** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** Build fingerprint: 'Android/aosp_flounder/flounder:5.1.51/AOSP/enh08201009:eng/test-keys' Revision: '0' ABI: 'arm' pid: 1656, tid: 1656, name: crasher >>> crasher <<< signal 6 (SIGABRT), code -6 (SI_TKILL), fault addr -------- Abort message: 'some_file.c:123: some_function: assertion "false" failed' r0 00000000 r1 00000678 r2 00000006 r3 f70b6dc8 r4 f70b6dd0 r5 f70b6d80 r6 00000002 r7 0000010c r8 ffffffed r9 00000000 sl 00000000 fp ff96ae1c ip 00000006 sp ff96ad18 lr f700ced5 pc f700dc98 cpsr 400b0010 backtrace: #00 pc 00042c98 /system/lib/libc.so (tgkill+12) #01 pc 00041ed1 /system/lib/libc.so (pthread_kill+32) #02 pc 0001bb87 /system/lib/libc.so (raise+10) #03 pc 00018cad /system/lib/libc.so (__libc_android_abort+34) #04 pc 000168e8 /system/lib/libc.so (abort+4) #05 pc 0001a78f /system/lib/libc.so (__libc_fatal+16) #06 pc 00018d35 /system/lib/libc.so (__assert2+20) #07 pc 00000f21 /system/xbin/crasher #08 pc 00016795 /system/lib/libc.so (__libc_init+44) #09 pc 00000abc /system/xbin/crasher Tombstone written to: /data/tombstones/tombstone_06 *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
Die Reihe von Sternchen mit Leerzeichen ist hilfreich, wenn Sie ein Protokoll nach systemeigenen Abstürzen durchsuchen. Die Zeichenfolge „*** ***“ taucht selten in Protokollen auf, außer zu Beginn eines nativen Absturzes.
Build fingerprint: 'Android/aosp_flounder/flounder:5.1.51/AOSP/enh08201009:eng/test-keys'
Anhand des Fingerabdrucks können Sie genau identifizieren, auf welchem Build der Absturz aufgetreten ist. Dies ist genau dasselbe wie die ro.build.fingerprint
.
Revision: '0'
Die Revision bezieht sich eher auf die Hardware als auf die Software. Dies wird normalerweise nicht verwendet, kann jedoch nützlich sein, um Ihnen zu helfen, automatisch Fehler zu ignorieren, von denen bekannt ist, dass sie durch schlechte Hardware verursacht werden. Dies ist genau dasselbe wie die ro.revision
.
ABI: 'arm'
Die ABI ist eine von arm, arm64, x86 oder x86-64. Dies ist vor allem für das oben erwähnte stack
Skript nützlich, damit es weiß, welche Toolchain es verwenden soll.
pid: 1656, tid: 1656, name: crasher >>> crasher <<<
Diese Zeile identifiziert den spezifischen Thread im Prozess, der abgestürzt ist. In diesem Fall war es der Hauptthread des Prozesses, daher stimmen die Prozess-ID und die Thread-ID überein. Der erste Name ist der Thread-Name, und der von >>> und <<< umgebene Name ist der Prozessname. Bei einer App ist der Prozessname normalerweise der vollständig qualifizierte Paketname (z. B. com.facebook.katana), was nützlich ist, wenn Sie Fehler melden oder versuchen, die App in Google Play zu finden. Die pid und tid können auch nützlich sein, um die relevanten Protokollzeilen vor dem Absturz zu finden.
signal 6 (SIGABRT), code -6 (SI_TKILL), fault addr --------
Diese Zeile sagt Ihnen, welches Signal (SIGABRT) empfangen wurde, und mehr darüber, wie es empfangen wurde (SI_TKILL). Die von debuggerd
gemeldeten Signale sind SIGABRT, SIGBUS, SIGFPE, SIGILL, SIGSEGV und SIGTRAP. Die signalspezifischen Codes variieren basierend auf dem spezifischen Signal.
Abort message: 'some_file.c:123: some_function: assertion "false" failed'
Nicht alle Abstürze haben eine Abbruchmeldungszeile, aber Abbrüche werden es tun. Dies wird automatisch aus der letzten Zeile der schwerwiegenden Logcat-Ausgabe für diese PID/TID gesammelt und liefert im Falle eines absichtlichen Abbruchs wahrscheinlich eine Erklärung dafür, warum sich das Programm selbst beendet hat.
r0 00000000 r1 00000678 r2 00000006 r3 f70b6dc8 r4 f70b6dd0 r5 f70b6d80 r6 00000002 r7 0000010c r8 ffffffed r9 00000000 sl 00000000 fp ff96ae1c ip 00000006 sp ff96ad18 lr f700ced5 pc f700dc98 cpsr 400b0010
Der Registerdump zeigt den Inhalt der CPU-Register zum Zeitpunkt des Signalempfangs. (Dieser Abschnitt variiert stark zwischen ABIs.) Wie nützlich diese sind, hängt vom genauen Absturz ab.
backtrace: #00 pc 00042c98 /system/lib/libc.so (tgkill+12) #01 pc 00041ed1 /system/lib/libc.so (pthread_kill+32) #02 pc 0001bb87 /system/lib/libc.so (raise+10) #03 pc 00018cad /system/lib/libc.so (__libc_android_abort+34) #04 pc 000168e8 /system/lib/libc.so (abort+4) #05 pc 0001a78f /system/lib/libc.so (__libc_fatal+16) #06 pc 00018d35 /system/lib/libc.so (__assert2+20) #07 pc 00000f21 /system/xbin/crasher #08 pc 00016795 /system/lib/libc.so (__libc_init+44) #09 pc 00000abc /system/xbin/crasher
Der Backtrace zeigt Ihnen, wo im Code wir uns zum Zeitpunkt des Absturzes befanden. Die erste Spalte ist die Frame-Nummer (passend zum Stil von gdb, wo der tiefste Frame 0 ist). Die PC-Werte beziehen sich eher auf den Speicherort der gemeinsam genutzten Bibliothek als auf absolute Adressen. Die nächste Spalte ist der Name der zugeordneten Region (die normalerweise eine gemeinsam genutzte Bibliothek oder eine ausführbare Datei ist, aber möglicherweise nicht für beispielsweise JIT-kompilierten Code). Wenn schließlich Symbole verfügbar sind, wird das Symbol, dem der PC-Wert entspricht, zusammen mit dem Offset in dieses Symbol in Bytes angezeigt. Sie können dies in Verbindung mit objdump(1)
verwenden, um die entsprechende Assembler-Anweisung zu finden.
Grabsteine lesen
Tombstone written to: /data/tombstones/tombstone_06
Dies sagt Ihnen, wo debuggerd
zusätzliche Informationen geschrieben hat. debuggerd
wird bis zu 10 Tombstones behalten, die Nummern 00 bis 09 durchlaufen und vorhandene Tombstones nach Bedarf überschreiben.
Der Tombstone enthält die gleichen Informationen wie der Crash-Dump, plus ein paar Extras. Beispielsweise enthält es Backtraces für alle Threads (nicht nur für den abstürzenden Thread), die Gleitkommaregister, Raw-Stack-Dumps und Speicherdumps um die Adressen in Registern herum. Am nützlichsten enthält es auch eine vollständige Speicherabbildung (ähnlich /proc/ pid /maps
). Hier ist ein kommentiertes Beispiel eines 32-Bit-ARM-Prozessabsturzes:
memory map: (fault address prefixed with --->) --->ab15f000-ab162fff r-x 0 4000 /system/xbin/crasher (BuildId: b9527db01b5cf8f5402f899f64b9b121)
Hier sind zwei Dinge zu beachten. Das erste ist, dass dieser Zeile das Präfix "--->" vorangestellt ist. Die Karten sind am nützlichsten, wenn Ihr Absturz nicht nur eine Nullzeiger-Dereferenzierung ist. Wenn die Fehleradresse klein ist, handelt es sich wahrscheinlich um eine Variante einer Nullzeiger-Dereferenzierung. Andernfalls kann Ihnen ein Blick auf die Karten um die Fehleradresse herum oft einen Hinweis darauf geben, was passiert ist. Einige mögliche Probleme, die beim Betrachten der Karten erkannt werden können, sind:
- Liest/schreibt über das Ende eines Speicherblocks hinaus.
- Liest/schreibt vor dem Beginn eines Speicherblocks.
- Versucht, Nicht-Code auszuführen.
- Laufen vom Ende eines Stapels.
- Versucht, in Code zu schreiben (wie im obigen Beispiel).
Als Zweites ist zu beachten, dass ausführbare Dateien und gemeinsam genutzte Bibliotheksdateien die BuildId (falls vorhanden) in Android 6.0 und höher anzeigen, sodass Sie genau sehen können, welche Version Ihres Codes abgestürzt ist. Plattform-Binärdateien enthalten seit Android 6.0 standardmäßig eine BuildId; NDK r12 und höher übergeben automatisch auch -Wl,--build-id
an den Linker.
ab163000-ab163fff r-- 3000 1000 /system/xbin/crasher ab164000-ab164fff rw- 0 1000 f6c80000-f6d7ffff rw- 0 100000 [anon:libc_malloc]
Unter Android ist der Heap nicht unbedingt eine einzelne Region. Heap-Regionen werden mit [anon:libc_malloc]
bezeichnet.
f6d82000-f6da1fff r-- 0 20000 /dev/__properties__/u:object_r:logd_prop:s0 f6da2000-f6dc1fff r-- 0 20000 /dev/__properties__/u:object_r:default_prop:s0 f6dc2000-f6de1fff r-- 0 20000 /dev/__properties__/u:object_r:logd_prop:s0 f6de2000-f6de5fff r-x 0 4000 /system/lib/libnetd_client.so (BuildId: 08020aa06ed48cf9f6971861abf06c9d) f6de6000-f6de6fff r-- 3000 1000 /system/lib/libnetd_client.so f6de7000-f6de7fff rw- 4000 1000 /system/lib/libnetd_client.so f6dec000-f6e74fff r-x 0 89000 /system/lib/libc++.so (BuildId: 8f1f2be4b37d7067d366543fafececa2) (load base 0x2000) f6e75000-f6e75fff --- 0 1000 f6e76000-f6e79fff r-- 89000 4000 /system/lib/libc++.so f6e7a000-f6e7afff rw- 8d000 1000 /system/lib/libc++.so f6e7b000-f6e7bfff rw- 0 1000 [anon:.bss] f6e7c000-f6efdfff r-x 0 82000 /system/lib/libc.so (BuildId: d189b369d1aafe11feb7014d411bb9c3) f6efe000-f6f01fff r-- 81000 4000 /system/lib/libc.so f6f02000-f6f03fff rw- 85000 2000 /system/lib/libc.so f6f04000-f6f04fff rw- 0 1000 [anon:.bss] f6f05000-f6f05fff r-- 0 1000 [anon:.bss] f6f06000-f6f0bfff rw- 0 6000 [anon:.bss] f6f0c000-f6f21fff r-x 0 16000 /system/lib/libcutils.so (BuildId: d6d68a419dadd645ca852cd339f89741) f6f22000-f6f22fff r-- 15000 1000 /system/lib/libcutils.so f6f23000-f6f23fff rw- 16000 1000 /system/lib/libcutils.so f6f24000-f6f31fff r-x 0 e000 /system/lib/liblog.so (BuildId: e4d30918d1b1028a1ba23d2ab72536fc) f6f32000-f6f32fff r-- d000 1000 /system/lib/liblog.so f6f33000-f6f33fff rw- e000 1000 /system/lib/liblog.so
Typischerweise hat eine gemeinsam genutzte Bibliothek drei benachbarte Einträge. Einer ist lesbar und ausführbar (Code), einer ist schreibgeschützt (schreibgeschützte Daten) und einer ist schreibgeschützt (änderbare Daten). Die erste Spalte zeigt die Adressbereiche für das Mapping, die zweite Spalte die Berechtigungen (im üblichen Unix- ls(1)
-Stil), die dritte Spalte den Offset in die Datei (in hex), die vierte Spalte die Größe der Region ( in Hex) und die fünfte Spalte die Datei (oder ein anderer Regionsname).
f6f34000-f6f53fff r-x 0 20000 /system/lib/libm.so (BuildId: 76ba45dcd9247e60227200976a02c69b) f6f54000-f6f54fff --- 0 1000 f6f55000-f6f55fff r-- 20000 1000 /system/lib/libm.so f6f56000-f6f56fff rw- 21000 1000 /system/lib/libm.so f6f58000-f6f58fff rw- 0 1000 f6f59000-f6f78fff r-- 0 20000 /dev/__properties__/u:object_r:default_prop:s0 f6f79000-f6f98fff r-- 0 20000 /dev/__properties__/properties_serial f6f99000-f6f99fff rw- 0 1000 [anon:linker_alloc_vector] f6f9a000-f6f9afff r-- 0 1000 [anon:atexit handlers] f6f9b000-f6fbafff r-- 0 20000 /dev/__properties__/properties_serial f6fbb000-f6fbbfff rw- 0 1000 [anon:linker_alloc_vector] f6fbc000-f6fbcfff rw- 0 1000 [anon:linker_alloc_small_objects] f6fbd000-f6fbdfff rw- 0 1000 [anon:linker_alloc_vector] f6fbe000-f6fbffff rw- 0 2000 [anon:linker_alloc] f6fc0000-f6fc0fff r-- 0 1000 [anon:linker_alloc] f6fc1000-f6fc1fff rw- 0 1000 [anon:linker_alloc_lob] f6fc2000-f6fc2fff r-- 0 1000 [anon:linker_alloc] f6fc3000-f6fc3fff rw- 0 1000 [anon:linker_alloc_vector] f6fc4000-f6fc4fff rw- 0 1000 [anon:linker_alloc_small_objects] f6fc5000-f6fc5fff rw- 0 1000 [anon:linker_alloc_vector] f6fc6000-f6fc6fff rw- 0 1000 [anon:linker_alloc_small_objects] f6fc7000-f6fc7fff rw- 0 1000 [anon:arc4random _rsx structure] f6fc8000-f6fc8fff rw- 0 1000 [anon:arc4random _rs structure] f6fc9000-f6fc9fff r-- 0 1000 [anon:atexit handlers] f6fca000-f6fcafff --- 0 1000 [anon:thread signal stack guard page]
Ab Android 5.0 benennt die C-Bibliothek die meisten ihrer anonym zugeordneten Regionen, sodass es weniger mysteriöse Regionen gibt.
f6fcb000-f6fccfff rw- 0 2000 [stack:5081]
Regionen mit dem Namen [stack: tid ]
sind die Stapel für die angegebenen Threads.
f6fcd000-f702afff r-x 0 5e000 /system/bin/linker (BuildId: 84f1316198deee0591c8ac7f158f28b7) f702b000-f702cfff r-- 5d000 2000 /system/bin/linker f702d000-f702dfff rw- 5f000 1000 /system/bin/linker f702e000-f702ffff rw- 0 2000 f7030000-f7030fff r-- 0 1000 f7031000-f7032fff rw- 0 2000 ffcd7000-ffcf7fff rw- 0 21000 ffff0000-ffff0fff r-x 0 1000 [vectors]
Ob Sie [vector]
oder [vdso]
hängt von der Architektur ab. ARM verwendet [vector]
, während alle anderen Architekturen [vdso]
verwenden.