診斷本機崩潰

以下部分包括常見的本機崩潰類型、樣本崩潰轉儲的分析以及邏輯刪除的討論。每個碰撞類型包括例如debuggerd與關鍵證據輸出突出來幫助你區分特定類型的崩潰。

中止

中止很有趣,因為它們是故意的。有許多不同的方式來中止(包括調用abort(3)失敗的assert(3)使用特定的Android致命記錄類型中的一種),但所有涉及調用abort 。要在通話abort信號,SIGABRT調用線程,所以一幀顯示“中止”,在libc.so加SIGABRT是事情看在debuggerd輸出認識到這一情況。

可能有一個明確的“中止消息”行。你也應該看看在logcat輸出看一下這個線程之前故意殺人記錄本身,因為不像assert(3)或高級別致命日誌工具, abort(3)不接受的消息。

安卓的當前版本內嵌的tgkill(2)系統調用,所以他們的籌碼是最容易閱讀的,與呼叫到最頂部中止(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 遵循原始 abort 調用(此處為第 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做的就是廢棄的state中的元素pthread_mutex_t*它被賦予。如果你看一下源代碼,你可以看到這個元素在結構,它告訴你,偏移量為0 pthread_mutex_lock被賦予了無效的指針0xC的。從第1幀,你可以看到,它被賦予通過指針readdir ,其提取mutex_從外地DIR*它給了。尋找在該結構中,可以看到mutex_是在偏移sizeof(int) + sizeof(size_t) + sizeof(dirent*)struct DIR ,其32位的設備上是4 + 4 + 4 = 12 =位於0xC,所以你發現的bug: readdir被調用者傳遞一個空指針。在這一點上,你可以粘貼在堆棧進棧工具找出在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Ø過濾器的Seccomp 。調用受限系統調用的線程將收到代碼為 SYS_SECCOMP 的 SIGSYS 信號。系統調用號將與架構一起顯示在原因行中。需要注意的是,系統調用號因架構而異。例如, readlinkat(2)系統調用是在x86號碼305,但267上的x86-64。 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)

僅對於 Android 10 中的 arm64,二進製文件和庫的可執行段被映射到內存只執行(不可讀取),作為一種針對代碼重用攻擊的強化技術。此緩解措施與其他緩解措施的相互作用很差,後來被刪除。

使代碼不可讀的原因,有意和無意的讀入標只執行到拋出內存段SIGSEGV與代碼SEGV_ACCERR 。這可能是由於錯誤、漏洞、數據與代碼混合(例如文字池)或有意的內存自省而發生的。

編譯器假定代碼和數據沒有混合,但手寫彙編可能會出現問題。在許多情況下,這些可以通過簡單地將常量移動到一個被固定.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 文件描述符清理器有助於捕獲文件描述符的常見錯誤,例如關閉後使用和雙重關閉。見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稱為不速之客。如果您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]