硬體輔助的 AddressSanitizer

如要瞭解如何讀取 HWASan 當機資訊,請參閱「瞭解 HWASan 報告」。

Hardware-assisted AddressSanitizer (HWASan) 是一款與 AddressSanitizer 相似的記憶體錯誤偵測工具。HWASan 與 ASan 相比,RAM 大幅減少,因此適合 整個系統清理作業HWASan 僅適用於 Android 10 以及更高版本,且僅適用於 AArch64 硬體

雖然 HWASan 主要用於 C/C++ 程式碼,但也可以協助偵錯會導致 C/C++ 在實作 Java 介面時發生當機的 Java 程式碼。這項功能相當實用,因為它會在記憶體錯誤發生時加以擷取,並直接指出相關程式碼。

您可以從 ci.android.com 將預先建構的 HWASan 映像檔刷新至支援的 Pixel 裝置 (詳細設定操作說明)。

相較於傳統 ASan,HWASan 具備以下特點:

  • 額外占用的 CPU 資源相近 (約 2 倍)
  • 額外占用程式碼的空間相近 (40 - 50%)
  • RAM 額外佔用的空間大幅減少 (10% - 35%)

HWASan 能夠偵測 ASan 可偵測到的錯誤:

  • 堆疊和堆積緩衝區溢位/反向溢位
  • 釋放後的堆積使用情況
  • 超出範圍的堆疊使用情況
  • 重複釋放/錯誤釋放

此外,HWASan 也會偵測回傳後的堆疊使用情形。

HWASan (與 ASan 相同) 與 UBSan 相容,兩者可以在目標上同時啟用。

實作詳細資料和限制

HWASan 是以記憶體標記方法為基礎,其中小型隨機標記值會與指標和記憶體位址範圍相關聯。回憶集錦 指標和記憶體標記必須相符。 HWASan 依賴 ARMv8 功能頂層位元組忽略 (TBI),也稱為 虛擬地址標記,用於儲存指標標記 地址中最高位元的值。

如要進一步瞭解 HWASan 的設計,請前往 Clang 說明文件網站。

根據設計,HWASAN 沒有 ASan 的大小受限紅色區域,無法用於偵測溢位情形;也沒有 ASan 的容量受限隔離區,無法用於偵測釋放後使用情形。因此,無論溢位大小為何或記憶體釋放時間有多久,HWAsan 都能偵測到錯誤。這讓 HWASan 比 ASan 更有優勢。

不過,HWASan 的標記值數量有限 (256),這表示在執行程式期間,錯過任何錯誤的機率為 0.4%。

需求條件

新版 (4.14 以上版本) 常見的 Android 核心支援 立即可用的 HWASan。Android 10 專屬分支版本不支援 HWASan。

Android 11 起,HWASan 可提供使用者空間支援。

如果您使用的是其他核心,則 HWASan 要求 Linux 核心接受系統呼叫引數中的標記指標。已在下列上游修補程式集實作此功能:

如果您使用自訂工具鍊進行建構,請確保其中包含所有 LLVM 修訂版本 c336557f

使用 HWASan

使用下列指令,使用 HWASan 建構整個平台:

lunch aosp_walleye-userdebug # (or any other product)
export SANITIZE_TARGET=hwaddress
m -j

為了方便起見,您可以在產品定義中加入 SANITIZE_TARGET 設定。 類似 aosp_coral_hwasan

對於熟悉 AddressSanitizer 的使用者來說,許多建構複雜性都已消失:

  • 不需要執行 make 兩次。
  • 漸進式建構作業可立即使用。
  • 不需要更新使用者資料。

部分 AddressSanitizer 限制也已移除:

  • 支援靜態執行檔。
  • 您可以略過 libc 以外的任何目標的清理作業。不過,和 ASan 不同的是 不要求如果程式庫經過淨化,則任何連結該程式庫的執行檔亦不得如此。

您可以自由切換相同 (或更高) 版本號碼的 HWASan 和一般映像檔。無須清除裝置。

如要略過模組的清理程序,請使用 LOCAL_NOSANITIZE := hwaddress (Android.mk) 或 sanitize: { hwaddress: false } (Android.bp)。

清除個別目標

只要 libc.so 也經過消毒,就可以在一般 (未消毒) 版本中為每個目標啟用 HWASan。在 bionic/libc/Android.bp 中的 "libc_defaults" 中,將 hwaddress: true 新增至 sanitize 區塊。然後對著目標進行同樣的操作。

請注意,清理 libc 可讓系統層級的堆積記憶體分配加上標記,以及檢查 libc.so 內記憶體作業的標記。即使在未啟用 HWASan 的二進位檔中,如果 libc.so 有錯誤的記憶體存取行為,這項功能也可能會偵測到錯誤 (例如 pthread_mutex_unlock() (在 delete() 互斥鎖上)。

如果整個平台是使用 HWASan 建構,則不需要變更任何建構檔案。

閃電所

為了進行開發作業,您可以將支援 HWASan 的 Android 開放原始碼計畫版本刷新到 Pixel 裝置 並使用 Flashstation,在系統上解鎖的系統啟動載入程式。 選取 _hwasan 目標,例如:aosp_flame_hwasan-userdebug如需詳細資訊,請參閱應用程式開發人員的 NDK 說明文件,瞭解 HWASan 的相關資訊。

更完善的堆疊追蹤

HWASan 使用以影格指標為基礎的快速解開器錄製堆疊 深入分析 計畫。Android 預設會在 AArch64 程式碼中啟用影格指標,因此在實際操作中運作良好。如果您需要透過受管理的程式碼解開,請在程序環境中設定 HWASAN_OPTIONS=fast_unwind_on_malloc=0。請注意,記憶體存取堆疊追蹤記錄預設會使用「慢速」解開器;這項設定只會影響配置和取消配置追蹤記錄。建議您 耗用大量 CPU 資源,視負載量而定。

符號化

請參閱「瞭解 HWASan 報告」中的「符號化」一節。

應用程式中的 HWASan

與 AddressSanitizer 類似,HWAsan 無法查看 Java 程式碼,但可以偵測 JNI 程式庫中的錯誤。在 Android 14 以下版本,執行 HWASan 系統「不」支援非 HWASan 裝置上的應用程式。

在 HWASan 裝置上,您可以使用 HWASan 檢查應用程式,方法是在 Make 中使用 SANITIZE_TARGET:=hwaddress 建構應用程式程式碼,或是在編譯器標記中使用 -fsanitize=hwaddress。在非 HWASan 裝置 (搭載 Android 14 以上版本) 上,必須新增 wrap.sh 檔案設定 LD_HWASAN=1。詳情請參閱 應用程式開發人員說明文件 ,掌握更多詳細資訊。