當 HWASan 工具偵測到記憶體錯誤時,該程序會以 abort()
終止,且
系統會輸出報表到 stderr 和 logcat。如同 Android 上的所有原生程式碼錯誤,HWASan 錯誤
在 /data/tombstones
下找到。
與一般原生程式碼錯誤相比,HWASan 會在「取消訊息」欄位中提供額外資訊 在墓碑頂端附近請參閱下方的堆積當機事件範例 (如需堆疊錯誤,請參閱下方注意事項,瞭解堆疊專屬章節)。
範例報表
*** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** Build fingerprint: 'google/flame_hwasan/flame:Tiramisu/MASTER/7956676:userdebug/dev-keys' Revision: 'DVT1.0' ABI: 'arm64' Timestamp: 2019-04-24 01:13:22+0000 pid: 11154, tid: 11154, name: sensors@1.0-ser >>> /vendor/bin/hw/android.hardware.sensors@1.0-service <<< signal 6 (SIGABRT), code -1 (SI_QUEUE), fault addr -------- Abort message: '==9569==ERROR: HWAddressSanitizer: tag-mismatch on address 0x00433ae20045 at pc 0x00623ae2a9cc READ of size 1 at 0x00433ae20045 tags: 5b/83 (ptr/mem) in thread T0 #0 0x7240450c68 (/system/lib64/vndk-sp-R/libcutils.so+0x8c68) #1 0x723dffd490 (/vendor/lib64/sensors.ssc.so+0x34490) #2 0x723e0126e0 (/vendor/lib64/sensors.ssc.so+0x496e0) [...] [0x00433ae20040,0x00433ae20060) is a small unallocated heap chunk; size: 32 offset: 5 Cause: use-after-free 0x00433ae20045 is located 5 bytes inside of 10-byte region [0x00433ae20040,0x00433ae2004a) freed by thread T0 here: #0 0x72404d1b18 (/system/lib64/libclang_rt.hwasan-aarch64-android.so+0x10b18) #1 0x723af23040 (/vendor/lib64/libgralloccore.so+0x5040) #2 0x723af23fa4 (/vendor/lib64/libgralloccore.so+0x5fa4) [...] previously allocated here: #0 0x72404ce554 (/system/lib64/libclang_rt.hwasan-aarch64-android.so+0xd554) #1 0x7240115654 (/apex/com.android.runtime/lib64/bionic/libc.so+0x43654) #2 0x7240450ac8 (/system/lib64/vndk-sp-R/libcutils.so+0x8ac8) [...] hwasan_dev_note_heap_rb_distance: 1 1023 hwasan_dev_note_num_matching_addrs: 0 hwasan_dev_note_num_matching_addrs_4b: 0 Thread: T0 0x006a00002000 stack: [0x007fc1064000,0x007fc1864000) sz: 8388608 tls: [0x00737702ffc0,0x007377033000) Memory tags around the buggy address (one tag corresponds to 16 bytes): 0x006f33ae1f80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x006f33ae1f90: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x006f33ae1fa0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x006f33ae1fb0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x006f33ae1fc0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x006f33ae1fd0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x006f33ae1fe0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x006f33ae1ff0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 =>0x006f33ae2000: 08 00 08 00 [83] 00 00 00 00 00 00 00 00 00 00 00 0x006f33ae2010: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x006f33ae2020: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x006f33ae2030: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x006f33ae2040: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x006f33ae2050: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x006f33ae2060: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x006f33ae2070: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x006f33ae2080: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 Tags for short granules around the buggy address (one tag corresponds to 16 bytes): 0x006f33ae1ff0: .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. =>0x006f33ae2000: 72 .. d0 .. [..] .. .. .. .. .. .. .. .. .. .. .. 0x006f33ae2010: .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. See https://clang.llvm.org/docs/HardwareAssistedAddressSanitizerDesign.html#short-granules for a description of short granule tags Registers where the failure occurred (pc 0x00623ae2a9cc): x0 0000007fc18623ec x1 5b0000433ae20045 x2 0000000000000013 x3 ffffffffffffffff x4 ffffffffffffffff x5 0000007fc1861da3 x6 6f7420676e696f47 x7 45522061206f6420 x8 0000000000000000 x9 0200006b00000000 x10 00000007fc18623f x11 5b0000433ae20040 x12 6f64206f7420676e x13 0a44414552206120 x14 0000000000000010 x15 ffffffffffffffff x16 000000737169ac94 x17 0000000000000007 x18 0000007377bd8000 x19 0000007fc1862498 x20 0200006b00000000 x21 0000007fc18624a8 x22 0000000000000001 x23 0000000000000000 x24 0000000000000000 x25 0000000000000000 x26 0000000000000000 x27 0000000000000000 x28 0000000000000000 x29 0000007fc1862410 x30 000000623ae2a9d0 sp 0000007fc18623d0 SUMMARY: HWAddressSanitizer: tag-mismatch (/system/lib64/vndk-sp-R/libcutils.so+0x8c68) [ … regular crash dump follows …]
這與 AddressSanitizer 報告非常類似。 與這些錯誤不同,幾乎所有 HWASan 錯誤都是「標記不相符」,也就是指標標記在記憶體存取方面存在的錯誤 與對應的記憶體標記不相符。這可以是
- 跨界存取堆疊或堆積
- 釋放後使用
- 返回堆疊後的使用後
版面
以下說明 HWASan 報告的各個部分:
存取錯誤
包含記憶體存取問題的相關資訊,包括:
- 存取類型 (「READ」和「WRITE」)
- 存取大小 (嘗試存取的位元組數量)
- 存取的執行緒編號
- 指標和記憶體標記 (適用於進階偵錯)
存取堆疊追蹤
錯誤記憶體存取行為的堆疊追蹤。請參閱「符號化」一節, 符號化。
原因
發生存取問題的可能原因。如果有多個候選人 是 並按照可能性由高至低排列就在關於 HWASan 可以診斷以下原因:
- 使用釋放後記憶體
- 堆疊標記不相符:這可以是堆疊使用後/返回使用/在範圍之後使用,或 超出範圍
- 堆積緩衝區溢位
- 全域溢位
記憶體資訊
說明 HWASan 對於所存取記憶體的瞭解 (可能不同) 根據 錯誤類型。
錯誤類型 | 原因 | 報表格式 |
---|---|---|
標記不符 | 使用釋放後記憶體 |
<address> is located N bytes inside of M-byte region [<start>, <end>) freed by thread T0 here: |
堆積緩衝區溢位 | 請注意,這也可能是一個反向溢位。
<address> is located N bytes to the right of M-byte region [<start>, <end>) allocated here: |
|
堆疊標記不相符 | 堆疊報表無法區分溢位/反向溢位和 找出錯誤率高低於 此外,如要找出錯誤來源的堆疊配置 離線 符號化步驟請參閱「瞭解堆疊報告」一文 以下章節。 | |
無無效 | 使用釋放後記憶體 | 這是重複釋放的錯誤。如果系統在程序關閉時發生這種情況
違反 ODR 規範。
<address> is located N bytes inside of M-byte region [<start>, <end>) freed by thread T0 here: |
無法描述地址 | 系統未分配到的可用記憶體 (沒有記憶體) 或 雙釋放 從 HWASan 可用緩衝區剔除分配的記憶體後。 | |
0x... 是 HWAsan 陰影記憶體。 | 由於應用程式試圖 記憶體容量 HWASan 內部。 |
Deallocation 堆疊追蹤
記憶體釋放位置的堆疊追蹤。只用於釋放後使用 或無無效錯誤 如要進行符號化處理,請參閱符號化部分。
配置堆疊追蹤
記憶體分配位置的堆疊追蹤。 如要進行符號化處理,請參閱符號化部分。
進階偵錯 資訊
HWASan 報告也提供一些進階偵錯資訊,包括 (依序):
- 程序中的執行緒清單
- 程序中的執行緒清單
- 錯誤記憶體附近記憶體標記的值
- 存取記憶體時的暫存器轉儲
記憶體標記轉儲
可使用標記記憶體傾印,使用相同標記尋找鄰近的記憶體配置 作為 指標 標記之前。這些物件可能會指向外界存取,並具有較大的偏移量。1 個代碼 相當於 16 個 個位元組 記憶體用量指標標記為位址的前 8 位元。標記記憶體傾印 給予提示 的 以下範例是右側的緩衝區溢位:
tags: ad/5c (ptr/mem) [...] Memory tags around the buggy address (one tag corresponds to 16 bytes): 0x006f33ae1ff0: 0e 0e 0e 57 20 20 20 20 20 2e 5e 5e 5e 5e 5e b5 =>0x006f33ae2000: f6 f6 f6 f6 f6 4c ad ad ad ad ad ad [5c] 5c 5c 5c 0x006f33ae2010: 5c 04 2e 2e 2e 2e 2e 2f 66 66 66 66 66 80 6a 6a Tags for short granules around the buggy address (one tag corresponds to 16 bytes): 0x006f33ae1ff0: ab 52 eb .. .. .. .. .. .. .. .. .. .. .. .. .. =>0x006f33ae2000: .. .. .. .. .. .. .. .. .. .. .. .. [..] .. .. .. 0x006f33ae2010: .. 5c .. .. .. .. .. .. .. .. .. .. .. .. .. ..(請注意,在符合指標代碼的情況下,左側為 6 × 16 的「廣告」標記執行 = 96 個位元組)。
如果分配的大小不是 16 的倍數,剩餘的大小會是 已儲存 作為 memory 標記,而標記則儲存為 short granule 標記,在上述範例中,緊接在加上粗體分配後才加上標示 我們 有 5 個 × 16 + 4 = 代碼 5c 的 84 位元配置。
零記憶體標記 (例如tags: ad/00 (ptr/mem)
) 通常表示
傳回堆疊使用後發生的堆疊錯誤
註冊轉儲作業
HWASan 報表中的註冊傾印可對應至 無效 個人化記憶 資源存取權後面接著來自一般 Android 信號處理常式的另一個註冊傾印 - 忽略 第二種是,則會在 HWASan 呼叫 abort() 時採用,且與 錯誤。
符號化
取得堆疊追蹤中的函式名稱和行數 (並取得「使用後範圍」的變數名稱) 錯誤時,則需要執行離線符號化步驟。
首次設定:安裝 llvm-symbolizer
如要進行符號化處理,你的系統必須安裝 llvm-symbolizer,並透過 $PATH 存取。使用 Debian 時
即可透過 sudo apt install llvm
安裝。
取得符號檔案
進行符號化處理時,不得使用含有符號且未移除的二進位檔。顯示方式取決於 處理:
對於本機版本,符號檔案位於
out/target/product/<product>/symbols/
。
如果是 Android 開放原始碼計畫版本 (例如從 Flashstation 刷新),
您可以在 Android CI 中找到這些版本。在「構件」中的
建構
會有 ${PRODUCT}-symbols-${BUILDID}.zip
檔案。
如要瞭解貴機構的內部版本,請參閱貴機構的說明文件來取得協助 取得符號檔案
符號化
hwasan_symbolize –-symbols <DECOMPRESSED_DIR>/out/target/product/*/symbols < crash
瞭解堆疊報表
如果是透過堆疊變數發生的錯誤,HWASan 報表會包含下列詳細資料:
Cause: stack tag-mismatch Address 0x007d4d251e80 is located in stack of thread T64 Thread: T64 0x0074000b2000 stack: [0x007d4d14c000,0x007d4d255cb0) sz: 1088688 tls: [0x007d4d255fc0,0x007d4d259000) Previously allocated frames: record_addr:0x7df7300c98 record:0x51ef007df3f70fb0 (/apex/com.android.art/lib64/libart.so+0x570fb0) record_addr:0x7df7300c90 record:0x5200007df3cdab74 (/apex/com.android.art/lib64/libart.so+0x2dab74) [...]
為了讓理解堆疊錯誤,HWASan 會追蹤過去發生的堆疊框架。 HWASan 目前無法在錯誤報告中呈現使用者可理解的內容,而且 需要額外的符號化步驟。
ODR 違規事項
HWASan 回報的部分釋放錯誤,也可能代表違反「單一定義規則」(ODR) 的情形。 如果在同一個程式中多次定義同一變數,就會發生 ODR 違規行為。 也就是說,變數會多次刪除, 「使用釋放後記憶體」錯誤。
符號化後,違反 ODR 規定顯示使用「__cxa_finalize
」的「釋放後記憶體」。
檢查無效存取堆疊與「在這裡釋放」「先前分配的
這裡」堆疊包含 __dl__ZN6soinfo17call_constructorsEv
,且應該
指向在程式中以更高層級定義變數的位置。
使用靜態資料庫時,可能違反 ODR 的原因之一。 如果定義 C++ 全域的靜態程式庫連結至多個共用程式庫, 可執行檔,同一個符號的多次定義最終可能位於同一個位址 所以會發生 ODR 錯誤
疑難排解
HWAddressSanitizer 無法詳細描述地址
HWASan 有時可能會用盡空間,以獲得有關過往記憶體配置的資訊。在這種情況下,報表 只會包含一個關於立即存取記憶體的堆疊追蹤,後接附註:
HWAddressSanitizer can not describe address in more detail.
在某些情況下,只要多次執行測試即可解決這個問題。另一個做法是增加 HWASan
記錄大小這項設定適用於全球各地
build/soong/cc/sanitize.go
(請尋找
hwasanGlobalOptions
) 或處理程序環境中 (嘗試
adb shell echo $HWASAN_OPTIONS
即可查看目前的設定)。
如果存取的記憶體未對應,或是由非 HWASan 感知的記憶體配置,也可能會發生這種情況
配置器。在這種情況下,當機標頭中列出的 mem
標記通常會是
00
。如果可以取得完整的空值標記,建議洽詢
記憶體對應傾印,來找出位址所屬的對應 (如果有的話)。
相同執行緒中的巢狀錯誤
這表示產生 HWASan 當機報告時發生錯誤。這通常是因為 HWASan 執行階段,請回報錯誤,然後 盡可能提供重現問題的操作說明。