診斷原生代碼崩潰問題

                                診斷原生代碼崩潰問題

以下部分包括原生代碼崩潰的常見類型、對示例崩潰轉儲的分析以及有關 tombstone 的討論。每種崩潰類型都包括示例 debuggerd 輸出,其中突出顯示的關鍵證據可以幫助您區分特定類型的崩潰問題。

提示:如果您之前從未遇到過原生代碼崩潰問題,請從調試原生 Android 平臺代碼着手。

中止

中止操作很有趣,因爲這是刻意而爲。執行中止操作可通過多種不同的方法(包括調用 abort(3)、使 assert(3)失敗、使用 Android 特有的嚴重記錄類型之一)來實現,但所有這些方法都涉及到調用 abortabort 調用會向調用線程發出 SIGABRT 信號,因此爲了識別這種情況,您需要在 debuggerd 輸出中查找以下兩項內容:libc.so 中顯示“abort”的幀,以及 SIGABRT 信號。

您可能會看到明確的“中止消息”行。不過,您還應該查看 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)

 

在原始中止調用(此處爲幀 4)與實際發送信號(此處爲幀 0)之間,較低版本的 Android 需要遵循複雜的路徑。特別是在 32 位 ARM 上運行的 Android,它會將 __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 來重現這類崩潰問題的實例。

純 Null 指針解引用

這是典型的原生代碼崩潰問題,雖然它只是下一類崩潰問題的特殊情況,但值得單獨說明,因爲這類崩潰問題通常無需細細思量。

在以下示例中,儘管崩潰函數在 libc.so 中,但由於字符串函數僅在指定給它們的指針處進行操作,因此您可以推斷出在調用 strlen(3) 時指定的是 Null 指針;對於這類崩潰問題,應直接找調用代碼的作者加以解決。在這種情況下,幀 #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 重現這類崩潰問題的實例。

低地址 Null 指針解引用

在許多情況下,故障地址將不會是 0,而是其他一些小數字。兩位或三位地址尤其常見,而六位地址幾乎肯定不是 Null 指針解引用(它需要 1 MiB 的偏移量)。通常,當您的代碼將 Null 指針解引用爲看似有效的結構時,就會出現這種情況。常見的函數是 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 元素。如果您查看源代碼,則會發現該元素在結構中的偏移量爲零,這表示指定給 pthread_mutex_lock 的指針 0xc 無效。從幀 1 可以看出,readdir 會將該指針指定給它,這會從指定的 DIR* 中提取 mutex_ 字段。通過查看該結構,您會發現 struct DIR 中 mutex_ 的偏移量爲 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-NULL 或 crasher readdir-NULL 重現此類崩潰問題的實例。

FORTIFY 失敗

FORTIFY 失敗是中止的一種特殊情況,當 C 庫檢測到可能導致安全漏洞的問題時,就會發生 FORTIFY 失敗。很多 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 過濾器。調用受限系統調用的線程將收到信號 SIGSYS 及代碼 SYS_SECCOMP。系統調用編號將與架構一起顯示在原因行中。需要注意的是,系統調用編號會因架構而異。例如,readlinkat(2) 系統調用在 x86 系統上的編號爲 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 重現此類崩潰問題的實例。

調查崩潰轉儲

如果您現在沒有正在調查的特定崩潰問題,則平臺來源包括用於測試 debuggerd 的工具,名爲 crasher。如果您在 system/core/debuggerd/ 中 mm,則您的路徑中會出現 crasher 和 crasher64(您可以藉助後者測試 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'

 

Revision 指的是硬件,而不是軟件。通常情況下不使用 revision,但使用 revision 有助於您自動忽略由不良硬件導致的已知錯誤。這與 ro.revision 系統屬性完全相同。

ABI: 'arm'

 

ABI 是 arm、arm64、mips、mips64、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

Tombstone written to: /data/tombstones/tombstone_06

 

您可由此得知 debuggerd 寫入額外信息的位置。 debuggerd 會保留最多 10 個 tombstone,從編號 00 至 09 循環並根據需要覆蓋現有 tombstone。

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

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

 

這裏需要注意兩點。第一點是該行帶有前綴“--->”。當您的崩潰問題不僅僅是 Null 指針解引用時,這些映射最有用。如果故障地址較小,則其很可能是 Null 指針解引用的某個變體。否則,通過查看故障地址周圍的映射,您通常可以瞭解發生的問題。通過查看映射可識別的一些可能存在的問題包括:

  • 讀/寫延伸到內存塊末尾之外。
  • 在內存塊開始之前讀/寫。
  • 嘗試執行非代碼內容。
  • 在堆棧末尾之外運行。
  • 嘗試寫入代碼(如上例所述)。

需要注意的第二點是,可執行文件和共享庫文件將在 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

 

通常,共享庫會有 3 個相鄰條目。一個是可讀且可執行條目(代碼),一個是隻讀條目(只讀數據),還有一個是讀寫條目(可變數據)。第一列顯示映射的地址範圍,第二列顯示權限(採用常規 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]

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章