W sekcjach poniżej znajdziesz typowe typy awarii natywnych, analizę
przykładowy zrzut awaryjny i dyskusję na temat elementów tombstone. Każdy rodzaj awarii obejmuje
przykładowy wynik debuggerd
z wyróżnionymi najważniejszymi dowodami w celu zapewnienia pomocy
rozróżnienie konkretnego rodzaju.
Przerwij
Przerwy są ciekawe, bo są zamierzone. Istnieje wiele różnych
sposoby przerywania pisania (w tym dzwonienia)
abort(3)
,
niezaliczenie
assert(3)
,
przy użyciu jednego z typów logów krytycznych specyficznych dla Androida), ale wszystkie
Wywołuję: abort
. Połączenie z numerem abort
oznacza nawiązanie połączenia
w wątku z SIGABRT, w ramce wyświetla się wtedy „przerwij” za libc.so
plus
SIGABRT to elementy, których należy szukać w danych wyjściowych debuggerd
, aby
rozpoznają ten przypadek.
Może wyświetlać się komunikat „Przerwij wiadomość” . Zaglądaj też do
Dane wyjściowe logcat
, aby sprawdzić, co ten wątek został celowo zarejestrowany wcześniej
zabijania się z powodu błędu assert(3)
lub wysokiego poziomu krytycznego.
punkty logowania, abort(3)
nie akceptuje komunikatu.
Aktualne wersje Androida wbudowane w
tgkill(2)
przez system, tak więc ich stosy są najłatwiejsze do odczytania, a wywołanie
abort(3) na samej górze:
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)
Starsze wersje Androida podążały krzywą ścieżką
przerwij wywołanie (ramka 4 tutaj) i rzeczywiste wysyłanie sygnału (ramka 0 tutaj).
Dotyczyło to zwłaszcza 32-bitowego procesora ARM,
__libc_android_abort
(ramka 3 tutaj) do innych platform”
sekwencja raise
/pthread_kill
/tgkill
:
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
Wystąpienie tego typu awarii możesz odtworzyć za pomocą narzędzia crasher
abort
.
Odwołanie do wskaźnika czystego zero
Jest to typowa awaria natywna, chociaż jest to tylko specjalny przypadek, następnego typu awarii, warto wspomnieć o nim oddzielnie, ponieważ zwykle wymaga on co najmniej u Ciebie.
W poniższym przykładzie, chociaż funkcja awarii jest
libc.so
, ponieważ funkcje ciągu znaków działają tylko na
otrzymane wskazówki, możesz to wywnioskować,
strlen(3)
została wywołana ze wskaźnikiem zerowym; a ta awaria powinna trafić prosto do
autor kodu dzwonienia. W tym przypadku klatka nr 01 to element wywołujący z błędem.
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)
Wystąpienie tego typu awarii możesz odtworzyć za pomocą narzędzia crasher
strlen-NULL
.
Odrzucenie wskaźnika null dla niskiego adresu
W wielu przypadkach adres błędu nie wynosi 0, ale w innych przypadkach jest to mała liczba. Dwa lub
trzycyfrowe adresy są bardzo powszechne, natomiast 6-cyfrowe
to na pewno nie jest odwołaniem do wskaźnika null,
wymaga przesunięcia 1 MiB. Dzieje się tak zwykle wtedy, gdy masz kod, który
usuwa odwołanie do wskaźnika o wartości null, tak jakby był to prawidłowy struct. Typowe funkcje to
fprintf(3)
(lub innej funkcji odbierającej PLIK*) i
readdir(3)
,
ponieważ kod często nie sprawdza, czy
fopen(3)
lub
opendir(3)
udało się zrealizować tylko początkowe wywołanie.
Oto przykład danych 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)
Bezpośrednią przyczyną awarii jest to,
pthread_mutex_lock(3)
Użytkownik próbował uzyskać dostęp do adresu 0xc (ramka 0). Najpierw jednak
pthread_mutex_lock
wykonuje odwołanie do state
podany element pthread_mutex_t*
. Jeśli spojrzysz na
element jest na pozycji 0 w elemencie struct, który wskazuje,
że interfejs pthread_mutex_lock
otrzymał nieprawidłowy wskaźnik 0xc. Od
a w ramce 1 widzimy, że dany wskaźnik został dzielony od readdir
,
który wyodrębnia pole mutex_
z DIR*
danej wartości. Patrząc na ten dom, widać, że mutex_
jest na
przesunięcie sizeof(int) + sizeof(size_t) + sizeof(dirent*)
w
struct DIR
, który na urządzeniach 32-bitowych to 4 + 4 + 4 = 12 = 0xc, więc
znaleziony błąd: funkcja readdir
otrzymała pusty wskaźnik
. Na tym etapie możesz wkleić stos do narzędzia stosu, aby sprawdzić,
gdzie to się stało.
struct DIR { int fd_; size_t available_bytes_; dirent* next_; pthread_mutex_t mutex_; dirent buff_[15]; long current_pos_; };
W większości przypadków możesz pominąć tę analizę. Wystarczająco niski błąd
oznacza zwykle, że można pominąć dowolną klatkę libc.so
i bezpośrednio oskarżać o kod wywołujący. Ale nie zawsze i w ten sposób
przedstawisz przekonujący przypadek.
Instancje tego typu awarii możesz odtworzyć za pomocą narzędzia crasher
fprintf-NULL
lub crasher readdir-NULL
.
Błąd FORTIFY
Awaria FORTIFY to specjalny przypadek przerwania, który występuje, gdy biblioteka C
wykrywa problem, który może prowadzić do luki w zabezpieczeniach. Wiele bibliotek C
funkcje są ufortyfikowane; przyjmuje dodatkowy argument,
w którym stwierdza
jak duży jest bufor i sprawdzić przy uruchamianiu, czy operacja
który chcesz wykonać. Oto przykład, w którym kod próbuje
do read(fd, buf, 32)
w buforze, który w rzeczywistości ma tylko 10 bajtów
długa...
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)
Wystąpienie tego typu awarii możesz odtworzyć za pomocą narzędzia crasher
fortify
.
Uszkodzenie stosu wykryte przez -fstack-protector
Opcja -fstack-protector
kompilatora wstawia testy do
z buforami na stosie, które pozwalają zapobiegać przeciążeniom buforów. Ta opcja
jest domyślnie włączone w przypadku kodu platformy, ale nie w aplikacjach. Gdy ta opcja jest
jest włączony, kompilator dodaje instrukcje do polecenia
funkcja
prolog, aby zapisać losową wartość tuż poza ostatnią lokalną w stosie,
do epiloga funkcji, aby go odczytać i sprawdzić, czy nie uległ zmianie. Jeśli
że ta wartość uległa zmianie, została zastąpiona przez przepełnienie bufora, przez co epilog
wywołuje __stack_chk_fail
, aby zapisać wiadomość i przerwać.
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)
Tę czynność można odróżnić od innych rodzajów przerw
__stack_chk_fail
w logu czasu wstecz i konkretnym komunikacie o przerwaniu.
Wystąpienie tego typu awarii możesz odtworzyć za pomocą narzędzia crasher
smash-stack
.
Seccomp SIGSYS w przypadku niedozwolonego wywołania systemowego
Seccomp
(konkretnie seccomp-bpf) ogranicza dostęp do wywołań systemowych. Więcej
informacje na temat seccomp dla programistów platform, zobacz post na blogu
Seccomp
w Androidzie O. Wątek, który wywołuje ograniczone wywołanie systemowe,
odbiera sygnał SIGSYS z kodem SYS_SECCOMP. Numer wywołania systemowego zostanie
widoczne na linii problemu
razem z architekturą. Trzeba pamiętać,
numery wywołań systemu różnią się w zależności od architektury. Na przykład parametr
Wywołanie systemu readlinkat(2)
to numer 305 w sieci x86, ale 267 w przypadku telefonów x86-64.
Numer połączenia jest inny w obu przypadkach. Ponieważ wywołanie systemowe
liczby różnią się w zależności od architektur, zwykle łatwiej jest użyć zrzutu stosu
jak sprawdzić, które wywołanie systemowe zostało odrzucone, zamiast szukać
systemowy numer systemowy.
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)
Niedozwolone wywołania systemowe można odróżnić od innych awarii na podstawie obecności
SYS_SECCOMP
w wierszu sygnału i opisie w wierszu przyczyny.
Wystąpienie tego typu awarii możesz odtworzyć za pomocą narzędzia crasher
seccomp
.
Naruszenie zasad tylko w zakresie wykonywania (tylko Android 10)
Tylko w przypadku arm64 na Androidzie 10: wykonywalne segmenty Zmapowano pliki binarne i biblioteki do pamięci tylko do wykonania (nieczytelnej) jako metody wzmacniania zabezpieczeń przed atakami polegającymi na ponownym wykorzystaniu kodu. To ograniczenie wpływało negatywnie na inne środki zaradcze, ale zostało później usunięte.
Ustawienie nieczytelnego kodu powoduje zamierzone i niezamierzone odczyty w segmentach pamięci oznaczonych
tylko do uruchomienia, co powoduje zgłoszenie SIGSEGV
z kodem SEGV_ACCERR
. Może to spowodować
występują w wyniku błędu, luki w zabezpieczeniach, danych zmieszanych z kodem (np. puli literału)
czy celowej refleksji pamięci.
Kompilator zakłada, że kod i dane nie są ze sobą wymieszane, ale problemy mogą powstać w przypadku pisma odręcznego
zmontowania elementów. W wielu przypadkach można po prostu przenieść stałe do funkcji .data
.
Jeśli introspekcja kodu jest absolutnie konieczna w przypadku sekcji kodu wykonywalnego,
mprotect(2)
należy wywołać najpierw, aby oznaczyć kod jako czytelny, a następnie ponownie, aby oznaczyć go jako nieczytelny po
.
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)
Przypadki naruszenia pamięci tylko podczas wykonywania możesz odróżnić od innych awarii według wiersza przyczyny.
Wystąpienie tego typu awarii możesz odtworzyć za pomocą narzędzia crasher xom
.
Błąd wykryty przez fdsan
Narzędzie fdsan na Androida do wykrywania deskryptorów plików pomaga wychwytywać typowe błędy deskryptorów plików, takich jak jak „używanie po zamknięciu” i „podwójny zamknięciu”. Zobacz Fdsan dokumentacja .
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)
Tę czynność można odróżnić od innych rodzajów przerw
fdsan_error
w logu czasu wstecz i konkretnym komunikacie o przerwaniu.
Wystąpienie tego typu awarii możesz odtworzyć za pomocą:
crasher fdsan_file
lub crasher fdsan_dir
.
Analizuj zrzuty po awarii
Jeśli nie masz żadnej konkretnej awarii, którą obecnie analizujesz, funkcja
źródło platformy zawiera narzędzie do testowania debuggerd
o nazwie
Jeśli mm
w system/core/debuggerd/
będzie
użyj zarówno crasher
, jak i crasher64
na swojej ścieżce (parametr
co pozwala na testowanie wersji 64-bitowej). Awaria może ulegać awarii w dużym
na różne ciekawe sposoby w oparciu o podane argumenty wiersza poleceń.
Użyj elementu crasher --help
, aby wyświetlić aktualnie obsługiwany wybór.
Omówmy teraz poszczególne elementy pliku zrzutu awaryjnego przykładowy zrzut awaryjny:
*** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** 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 *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
Wiersz gwiazdek ze spacjami jest przydatny, jeśli przeszukujesz dziennik pod kątem awarii natywnych. Ciąg „*** ***” rzadko pojawia się w dziennikach innych niż na początku awarii natywnej.
Build fingerprint: 'Android/aosp_flounder/flounder:5.1.51/AOSP/enh08201009:eng/test-keys'
Odcisk cyfrowy pozwala dokładnie zidentyfikować kompilację, w której wystąpiła awaria.
Działa dokładnie tak samo jak system ro.build.fingerprint
usłudze.
Revision: '0'
Wersja odnosi się do sprzętu, a nie oprogramowania. Zwykle jest to
nieużywane, ale mogą być przydatne do automatycznego ignorowania błędów, o których wiadomo,
z powodu wadliwego sprzętu. To dokładnie to samo co
Właściwość systemowa ro.revision
.
ABI: 'arm'
Interfejs ABI to armia: arm64, x86 lub x86-64. Dotyczy to głównie
przydatny w przypadku wspomnianego wyżej skryptu stack
, dzięki czemu wie
którego łańcucha narzędzi
użyć.
pid: 1656, tid: 1656, name: crasher >>> crasher <<<
Ten wiersz wskazuje konkretny wątek w procesie, który uległ awarii. W tym był taki proces, w wątku głównym, aby identyfikatory procesu i wątku były takie same. Imię to nazwa wątku, a nazwa w nawiasie >>> oraz <<< to nazwa procesu. W przypadku aplikacji nazwa procesu to zazwyczaj pełną i jednoznaczną nazwę pakietu (np. com.facebook.katana), przydatne przy zgłaszaniu błędów lub wyszukiwaniu aplikacji w Google Play. Pid i Parametr tid może również być pomocny w znajdowaniu odpowiednich wierszy logu poprzedzających awarię.
signal 6 (SIGABRT), code -6 (SI_TKILL), fault addr --------
Wiersz ten informuje o tym, który sygnał (SIGABRT) został odebrany, oraz o sposobie jego
otrzymano (SI_TKILL). Sygnały zgłoszone przez debuggerd
to
SIGABRT, SIGBUS, SIGFPE, SIGILL, SIGSEGV i SIGTRAP. W zależności od sygnału
różnią się w zależności od konkretnego sygnału.
Abort message: 'some_file.c:123: some_function: assertion "false" failed'
Nie w przypadku każdej awarii wyświetlany jest wiersz komunikatu z komunikatem o przerwanym działaniu – powoduje to przerwanie. To jest zebrane automatycznie z ostatniego wiersza krytycznych danych wyjściowych logcat dla tego pid/tid, a w przypadku celowej aborcji przypuszczalnie wyjaśnień, dlaczego program się zawiesił.
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
Zrzut rejestru pokazuje zawartość rejestrów procesora w momencie Odebrano sygnał. (Ta sekcja znacznie się różni w przypadku różnych interfejsów ABI). Na ile przydatna Zależą one od konkretnej awarii.
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
Ślad wsteczny pokazuje, w którym miejscu kodu byliśmy w momencie awarii.
pierwsza kolumna to numer klatki (dopasowanie stylu gdb, gdzie najgłębsza klatka
wynosi 0). Wartości PC odnoszą się do lokalizacji udostępnianych zasobów, a nie do
niż adresy bezwzględne. Następna kolumna to nazwa zmapowanego regionu
(który jest zwykle biblioteką współdzieloną lub plikiem wykonywalnym, ale może nie być np.
kodu skompilowanego przez JIT). Jeśli dostępne są symbole, oznacza to, że komputer
której wartość odpowiada wyświetleniom, wraz z przesunięciem do tego symbolu w argumencie
B. Możesz tego używać w połączeniu z operatorem objdump(1)
, by znaleźć
z odpowiedniej instrukcji asemblera.
Czytaj nagrobki
Tombstone written to: /data/tombstones/tombstone_06
Wskazuje, gdzie debuggerd
zapisał dodatkowe informacje.
debuggerd
przechowuje do 10 nagrobków, pokonując je rowerem
cyfr 00–09 i w razie potrzeby zastępując istniejące nagrobki.
Nagrobek zawiera te same informacje co zrzut po awarii oraz kilka
Dodatki. Obejmuje na przykład wycofane informacje dla wszystkich wątków (nie
po awarii wątku), rejestry zmiennoprzecinkowe, nieprzetworzone zrzuty stosu
adresy w rejestrach są zapisywane w pamięci. Najbardziej przydatne jest też
zawiera pełną mapę pamięci (podobną do /proc/pid/maps
).
Oto przykład awarii 32-bitowego procesu ARM z adnotacjami:
memory map: (fault address prefixed with --->) --->ab15f000-ab162fff r-x 0 4000 /system/xbin/crasher (BuildId: b9527db01b5cf8f5402f899f64b9b121)
Warto zwrócić uwagę na 2 rzeczy. Po pierwsze, ten wiersz jest prefiksem „--->”. Mapy są najbardziej przydatne, gdy wypadek nie jest tylko zera usunięcia wskaźnika. Jeśli adres błędu jest mały, prawdopodobnie jest to jakiś wariant w przypadku usunięcia wskaźnika zerowego. W przeciwnym razie patrzenie na mapy wokół usterki często jest wskazówką co do tego, co się stało. Niektóre możliwe problemy które można rozpoznać na mapach, to między innymi:
- Odczyty/zapisy po końcu bloku pamięci.
- Odczyt/zapisy przed początkiem bloku pamięci.
- Próby wykonania bez kodu.
- Koniec stosu.
- Próbuje zapisać kod w kodzie (jak w przykładzie powyżej).
Warto zauważyć, że pliki wykonywalne i pliki bibliotek udostępnionych
w Androidzie 6.0 i nowszych wersjach można dokładnie zobaczyć,
która wersja kodu uległa awarii. Pliki binarne platformy zawierają identyfikator BuildId przez
domyślnie od Androida 6.0; NDK r12 i nowsze automatycznie zaliczone
-Wl,--build-id
także do tagu łączącego.
ab163000-ab163fff r-- 3000 1000 /system/xbin/crasher ab164000-ab164fff rw- 0 1000 f6c80000-f6d7ffff rw- 0 100000 [anon:libc_malloc]
Na Androidzie sterta nie musi być pojedynczym regionem. Regiony sterty będą
zostaną oznaczone etykietą [anon:libc_malloc]
.
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
Biblioteka udostępniona ma zwykle trzy sąsiadujące ze sobą pozycje. Jedna z nich jest czytelna,
wykonywalny (kod), jeden jest tylko do odczytu (dane tylko do odczytu), a drugi to odczyt i zapis
(dane zmienne). Pierwsza kolumna zawiera zakresy adresów dla mapowania,
w drugiej kolumnie uprawnień (w typowym stylu uniksowym ls(1)
),
trzecia kolumna to przesunięcie do pliku (wartość szesnastkowa), a czwarta kolumna – rozmiar.
regionu (w postaci szesnastkowej), a piąta kolumna to nazwa pliku (lub innej nazwy regionu).
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]
Począwszy od Androida 5.0 biblioteka C nazywa większość swoich anonimowych mapowanych regionów, jest mniej tajemniczych regionów.
f6fcb000-f6fccfff rw- 0 2000 [stack:5081]
Regiony o nazwie [stack:tid]
to stosy danej
.
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]
To, czy widzisz [vector]
czy [vdso]
, zależy od
i architekturą. ARM używa interfejsu [vector]
, a pozostałe architektury –
[vdso]