Google致力於提高黑人社區的種族平等。 怎麼看。
本頁面由 Cloud Translation API 翻譯而成。
Switch to English

診斷本機崩潰

以下各節包括常見的本機崩潰類型,對示例崩潰轉儲的分析以及對邏輯刪除的討論。每種崩潰類型都包括示例debuggerd輸出,突出顯示了關鍵證據,以幫助您區分特定的崩潰類型。

中止

中止很有趣,因為它們是故意的。有許多不同的方法來中止(包括使用特定於Android的致命日誌記錄類型之一來調用abort(3) ,使assert(3)失敗),但是所有方法都涉及到調用abortabort的調用會用SIGABRT發出信號給正在調用的線程,因此在libc.so和SIGABRT中顯示“異常終止”的幀就是在debuggerd輸出中尋找的事情,以識別這種情況。

可能有一個明確的“中止消息”行。您還應該在logcat輸出中查看該線程在故意殺死自己之前記錄的內容,因為與assert(3)或高級致命日誌記錄功能不同, abort(3)不接受消息。

當前版本的Android內聯了tgkill(2)系統調用,因此最容易讀取它們的堆棧,其中最頂部的是abort(3)的調用:

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)

較舊版本的Android在原始中止調用(此處為第4幀)與實際發送信號(此處為第0幀)之間遵循複雜的路徑。在32位ARM上尤其如此,它將__libc_android_abort (此處為第3幀)添加到其他平台的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

您可以使用crasher abort重現此類崩潰的實例。

純空指針取消引用

這是經典的本機崩潰,儘管它只是下一個崩潰類型的特例,但值得一提,因為它通常需要最少的思考。

在下面的示例中,即使崩潰函數在libc.so ,由於字符串函數僅在給定它們的指針上運行,因此您可以推斷strlen(3)是用空指針調用的;並且此崩潰應直接歸於調用代碼的作者。在這種情況下,幀#01是錯誤的呼叫者。

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)

您可以使用crasher strlen-NULL複製此類崩潰的實例。

低地址空指針取消引用

在許多情況下,故障地址不是0,而是其他一些低數字。特別是兩位數或三位數的地址非常常見,而六位數的地址幾乎可以肯定不是空指針取消引用,這需要1MiB的偏移量。通常,當您具有取消引用空指針的代碼時,就好像它是一個有效的結構一樣。常見函數是fprintf(3) (或其他任何帶有FILE *的函數)和readdir(3) ,因為代碼通常無法檢查fopen(3)opendir(3)調用實際上是否首先成功。

這是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)

導致崩潰的直接原因是pthread_mutex_lock(3)試圖訪問地址0xc(幀0)。但是pthread_mutex_lock要做的第一件事就是取消引用給定的pthread_mutex_t*state元素。如果您查看源代碼,可以看到該元素在結構中的偏移量為0,這告訴您pthread_mutex_lock被賦予了無效的指針0xc。從第1幀中,您可以看到readdir給了它指針,它從給定的DIR*提取了mutex_字段。查看該結構,您可以看到mutex_struct DIR中的偏移量為sizeof(int) + sizeof(size_t) + sizeof(dirent*) ,在32位設備上為4 + 4 + 4 = 12 = 0xc,因此,您發現了一個錯誤:調用者將readdir傳遞給了null指針。在這一點上,你可以粘貼在堆棧進棧工具找出在logcat中發生這種情況。

  struct DIR {
    int fd_;
    size_t available_bytes_;
    dirent* next_;
    pthread_mutex_t mutex_;
    dirent buff_[15];
    long current_pos_;
  };

在大多數情況下,您實際上可以跳過此分析。足夠低的故障地址通常意味著您可以跳過堆棧中的任何libc.so幀並直接控制調用代碼。但並非總是如此,這就是您提出令人信服的案例的方式。

您可以使用crasher fprintf-NULLcrasher readdir-NULL複製此類崩潰的實例。

修復失敗

FORTIFY故障是C庫檢測到可能導致安全漏洞的問題時發生異常終止的一種特殊情況。許多C庫函數得到加強 ;他們使用一個額外的參數來告訴他們緩衝區實際上有多大,並在運行時檢查您嘗試執行的操作是否真正適合。這是一個示例,其中代碼嘗試read(fd, buf, 32)到實際上只有10個字節長的緩衝區中...

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)

您可以使用crasher fortify重現此類崩潰的實例。

-fstack-protector檢測到堆棧損壞

編譯器的-fstack-protector選項將檢查插入具有堆棧緩衝區的函數中,以防止緩衝區溢出。默認情況下,平台代碼啟用此選項,但應用程序則不啟用。啟用此選項後,編譯器會將指令添加到函數序言中,以在堆棧的最後一個本地變量之後寫入一個隨機值,並在函數附錄中將其讀回並檢查其是否未更改。如果該值發生更改,那麼它會被緩衝區溢出所覆蓋,因此結語調用__stack_chk_fail記錄消息併中止。

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)

您可以通過在回溯中存在__stack_chk_fail以及特定的中止消息來將其與其他類型的中止區分開。

您可以使用crasher smash-stack重現此類崩潰的實例。

來自不允許的系統調用的Seccomp SIGSYS

seccomp系統(特別是seccomp-bpf)限制對系統調用的訪問。有關面向平台開發人員的seccomp的更多信息,請參閱博客文章Android O中的Seccomp過濾器 。調用受限系統調用的線程將收到代碼為SYS_SECCOMP的SIGSYS信號。系統調用號將與體系結構一起顯示在原因行中。重要的是要注意,系統調用號在體系結構之間有所不同。例如,在x86上, readlinkat(2)系統調用是305,而在x86-64上是267。 arm和arm64上的呼叫號碼再次不同。因為體系結構之間的系統調用號不同,所以通常使用堆棧跟踪來查找不允許的系統調用比在標頭中查找系統調用號更容易。

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)

您可以通過信號線上的SYS_SECCOMP和原因線上的描述來區分不允許的系統調用與其他崩潰。

您可以使用crasher seccomp複製此類崩潰的實例。

僅執行內存衝突

對於Android 10及更高版本中的arm64,二進製文件和庫的可執行段被映射到僅執行(不可讀)內存中,作為一種針對代碼重用攻擊的強化技術。可以通過在可執行存儲器中搜索已知功能或通過構建小工具鏈來使讀原語繞過地址空間佈局隨機化(ASLR),而無需事先了解存儲器佈局。通過將可執行代碼標記為不可讀,讀取的原語無法訪問可執行內存,從而關閉了整個開發技術類別。這不僅提高了ASLR的效率,而且還提高了控制流完整性(CFI),因為有效的目標不再能夠顯示給具有讀取原語的攻擊者。

使代碼無法讀取會導致有意和無意地讀取標記為僅執行的內存段,從而引發代碼為SEGV_ACCERRSIGSEGV 。這可能是由於錯誤,漏洞,數據與代碼混合(例如文字池)或故意進行內存自檢而導致的。

編譯器假定代碼和數據沒有混合在一起,但是手寫組裝可能會引起問題。在許多情況下,可以通過簡單地將常量移動到.data節來解決這些問題。如果對可執行代碼節絕對必須進行代碼自省,則應首先調用mprotect(2)以將代碼標記為可讀,然後在操作完成後再次將其標記為不可讀。

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)

您可以通過原因行將僅執行內存衝突與其他崩潰區別開來。

您可以使用crasher xom複製此類崩潰的實例。

fdsan檢測到錯誤

Android的fdsan文件描述符清理程序可幫助捕獲文件描述符中的常見錯誤,例如use-after-close和double-close。有關調試(和避免)此類錯誤的更多詳細信息,請參見fdsan文檔

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)

通過在回溯中存在fdsan_error和特定的中止消息,可以將其與其他類型的中止區分開。

您可以使用crasher fdsan_filecrasher fdsan_dir複製此類崩潰的實例。

調查故障轉儲

如果您現在沒有正在調查的特定崩潰,那麼該平台源代碼包括一個用於測試debuggerd的工具,稱為rasher。如果您mmsystem/core/debuggerd/你會得到一兩個crashercrasher64您的路徑上(後者還可以測試64位崩潰)。根據您提供的命令行參數,Crasher可能會以多種有趣的方式崩潰。使用crasher --help查看當前支持的選擇。

為了在故障轉儲中介紹不同的部分,讓我們研究以下示例故障轉儲:

*** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
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
*** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***

如果要在日誌中搜索本機崩潰,則帶空格的星號行會很有幫助。除了本機崩潰的開始之外,字符串“ *** ***”很少出現在日誌中。

Build fingerprint:
'Android/aosp_flounder/flounder:5.1.51/AOSP/enh08201009:eng/test-keys'

指紋使您可以準確識別崩潰發生在哪個建築物上。這與ro.build.fingerprint系統屬性完全相同。

Revision: '0'

該修訂版是指硬件而不是軟件。這通常是未使用的,但是對於幫助您自動忽略已知由不良硬件引起的錯誤很有用。這與ro.revision系統屬性完全相同。

ABI: 'arm'

ABI是arm,arm64,x86或x86-64之一。這對於上面提到的stack腳本最有用,因此它知道要使用的工具鏈。

pid: 1656, tid: 1656, name: crasher >>> crasher <<<

此行標識崩潰的進程中的特定線程。在這種情況下,它是進程的主線程,因此進程ID和線程ID匹配。名字是線程名稱,用>>>和<<<包圍的名稱是進程名稱。對於應用程序,進程名稱通常是標準的程序包名稱(例如com.facebook.katana),在提交錯誤或嘗試在Google Play中查找應用程序時非常有用。 pid和tid還可用於查找崩潰之前的相關日誌行。

signal 6 (SIGABRT), code -6 (SI_TKILL), fault addr --------

此行告訴您接收到哪個信號(SIGABRT),以及有關如何接收的更多信息(SI_TKILL)。 debuggerd報告的信號是SIGABRT,SIGBUS,SIGFPE,SIGILL,SIGSEGV和SIGTRAP。信號特定代碼根據特定信號而有所不同。

Abort message: 'some_file.c:123: some_function: assertion "false" failed'

並非所有的崩潰都具有中止消息行,但是中止將會。這是從此pid / tid的致命logcat輸出的最後一行自動收集的,在故意中止的情況下,很可能會說明程序為何自行終止。

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

寄存器轉儲顯示了接收信號時CPU寄存器的內容。 (本節在ABI之間千差萬別。)它們的用處取決於確切的崩潰。

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

回溯向您顯示崩潰時代碼在哪裡。第一列是幀​​號(與gdb的樣式匹配,其中最深的幀為0)。 PC值是相對於共享庫的位置而不是絕對地址。下一列是映射區域的名稱(通常是共享庫或可執行文件,但可能不適用於JIT編譯的代碼)。最後,如果有可用符號,則會顯示PC值對應的符號以及該符號的偏移量(以字節為單位)。您可以將其與objdump(1)結合使用以找到相應的彙編器指令。

閱讀墓碑

Tombstone written to: /data/tombstones/tombstone_06

這告訴您debuggerd在哪裡寫了額外的信息。 debuggerd將保留最多10個邏輯刪除,在數字00到09之間循環,並根據需要覆蓋現有的邏輯刪除。

邏輯刪除包含與故障轉儲相同的信息,以及一些其他信息。例如,它包括所有線程(不僅是崩潰線程)的回溯,浮點寄存器,原始堆棧轉儲以及寄存器中地址周圍的內存轉儲。最有用的是,它還包括完整的內存映射(類似於/proc/ pid /maps )。這是一個32位ARM進程崩潰的註釋示例:

memory map: (fault address prefixed with --->)
--->ab15f000-ab162fff r-x 0 4000 /system/xbin/crasher (BuildId:
b9527db01b5cf8f5402f899f64b9b121)

這裡有兩件事要注意。首先是該行以“ --->”為前綴。當崩潰不僅僅是空指針取消引用時,映射最有用。如果故障地址很小,則可能是空指針取消引用的某種變體。否則,查看故障地址周圍的地圖通常可以為您提供有關發生情況的線索。通過查看地圖可以識別的一些可能的問題包括:

  • 讀/寫超過內存塊的末尾。
  • 在內存塊開始之前進行讀/寫。
  • 嘗試執行非代碼。
  • 在堆棧末尾運行。
  • 嘗試寫代碼(如上例所示)。

要注意的第二件事是可執行文件和共享庫文件將在Android 6.0及更高版本中顯示BuildId(如果存在),因此您可以確切地看到崩潰的代碼版本。自Android 6.0起,平台二進製文件默認包含BuildId; NDK r12及更高版本也自動將-Wl,--build-id傳遞給鏈接器。

ab163000-ab163fff r--      3000      1000  /system/xbin/crasher
ab164000-ab164fff rw-         0      1000
f6c80000-f6d7ffff rw-         0    100000  [anon:libc_malloc]

在Android上,堆不一定是單個區域。堆區域將被標記為[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

通常,共享庫具有三個相鄰的條目。一種是可讀且可執行的(代碼),一種是只讀的(只讀數據),一種是讀寫的(可變數據)。第一列顯示映射的地址範圍,第二列顯示權限(在通常的Unix ls(1)樣式中),第三列顯示文件的偏移量(十六進制),第四列區域的大小( (以十六進製表示),第五列為文件(或其他區域名稱)。

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]

從Android 5.0開始,C庫會為其大部分匿名映射區域命名,因此神秘區域更少。

f6fcb000-f6fccfff rw- 0 2000 [stack:5081]

名為[stack: tid ]是給定線程的堆棧。

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]

您看到[vector]還是[vdso]取決於體系結構。 ARM使用[vector] ,而所有其他體系結構使用[vdso]