Android NDK は、NDK r21 および Android 10(API レベル 29)以降で HWAddressSanitizer(HWASan)をサポートしています。HWASan は 64 ビットの Arm デバイスでのみ使用できます。
HWASan は ASan と似たメモリエラー検出ツールです。従来の ASan と比較した HWASan の特徴を次に示します。
- CPU オーバーヘッドは同程度(~2 倍)
- コードサイズ オーバーヘッドは同程度(40~50%)
- RAM オーバーヘッドは大幅に少ない(10~35%)
HWASan は ASan と同じ種類のバグを検出します。
- スタックとヒープのバッファ オーバーフロー / アンダーフロー
- 解放後のヒープ使用
- スコープ外のスタック使用
- 二重解放 / ワイルド解放
さらに、HWASan は以下も検出します。
- 返却後のスタック使用
サンプルアプリ
サンプルアプリは、HWASan 用にビルド バリアントを構成する方法を示しています。
セットアップ
HWASan アプリを実行するは、Android の HWASan ビルドが必要です。サポートされている Pixel デバイスに、事前ビルド済みの HWASan イメージをフラッシュできます。ビルドは ci.android.com で入手できます。ここでは、正確なビルド(正方形)をクリックすると、[Flash Build] リンクが表示されます。そのためには、使用しているスマートフォンのコードネームを知る必要があります。
このフローは、最初にデバイスを検出した後、使用可能なビルドのみを表示します。したがって、flash.android.com に直接アクセスするほうが簡単な場合があります。以下の画像は、このツールの設定フローを示しています。
デバイスでデベロッパー モードを有効にし、USB ケーブルを使用してデバイスをパソコンに接続します。[Add new device] をクリックし、ダイアログからデバイスを選択して、[Connect] をクリックします。
デバイスが接続されたら、デバイスをクリックしてビルドを設定する必要があります。[Select a build ID] ボックスで aosp-master-with-phones-throttled
ブランチを選択すると、接続したデバイス用の正しいイメージが自動的に選択されます。
[Install] をクリックしてデバイスをフラッシュします。
必要な設定の詳細については、Android Flash Tool のドキュメントをご覧ください。または、ソースから HWASan イメージをビルドすることもできます。その手順については、AOSP のドキュメントで確認してください。
構築
HWAddressSanitizer を使用してアプリのネイティブ(JNI)コードをビルドする手順は次のとおりです。
ndk-build
Application.mk
ファイルに以下の行を追加します。
APP_STL := c++_shared # Or system, or none, but not c++_static.
APP_CFLAGS := -fsanitize=hwaddress -fno-omit-frame-pointer
APP_LDFLAGS := -fsanitize=hwaddress
CMake
モジュールの build.gradle
ファイルに以下の行を追加します。
android {
defaultConfig {
externalNativeBuild {
cmake {
# Can also use system or none as ANDROID_STL, but not c++_static.
arguments "-DANDROID_STL=c++_shared"
}
}
}
}
CMakeLists.txt 内の各ターゲットごとに、以下のように指定します。
target_compile_options(${TARGET} PUBLIC -fsanitize=hwaddress -fno-omit-frame-pointer)
set_target_properties(${TARGET} PROPERTIES LINK_FLAGS -fsanitize=hwaddress)
実行
通常どおり、HWASan でビルドされた Android イメージでアプリを実行します。メモリエラーが検出されると、アプリは SIGABRT によりクラッシュし、詳細なメッセージを logcat に出力します。メッセージのコピーは /data/tombstones
のファイル内にあり、次のように表示されます。
ERROR: HWAddressSanitizer: tag-mismatch on address 0x0042a0826510 at pc 0x007b24d90a0c
WRITE of size 1 at 0x0042a0826510 tags: 32/3d (ptr/mem) in thread T0
#0 0x7b24d90a08 (/data/app/com.example.hellohwasan-eRpO2UhYylZaW0P_E0z7vA==/lib/arm64/libnative-lib.so+0x2a08)
#1 0x7b8f1e4ccc (/apex/com.android.art/lib64/libart.so+0x198ccc)
#2 0x7b8f1db364 (/apex/com.android.art/lib64/libart.so+0x18f364)
#3 0x7b8f2ad8d4 (/apex/com.android.art/lib64/libart.so+0x2618d4)
0x0042a0826510 is located 0 bytes to the right of 16-byte region [0x0042a0826500,0x0042a0826510)
allocated here:
#0 0x7b92a322bc (/apex/com.android.runtime/lib64/bionic/libclang_rt.hwasan-aarch64-android.so+0x212bc)
#1 0x7b24d909e0 (/data/app/com.example.hellohwasan-eRpO2UhYylZaW0P_E0z7vA==/lib/arm64/libnative-lib.so+0x29e0)
#2 0x7b8f1e4ccc (/apex/com.android.art/lib64/libart.so+0x198ccc)
アプリ内のライブスレッドのリスト、隣接するメモリの割り当てのタグ、CPU レジスタ値など、追加のデバッグ情報がメッセージの後に続くこともあります。
HWASan エラー メッセージの詳細については、HWASan レポートについてをご覧ください。