API level 27 から Android でも ASAN(Address Sanitizer)が使えるようになりました.
(APL level 24 くらいから使えたような気もしますが, セットアップのしかたが変わったようです)
ビルド
ドキュメント通りにすればいけます.
特段, gradle や CMake での ASAN 専用設定オプションはありません.
CFLAGS/LDFLAGS に直接 -fsanitize=address
あたりを指定します.
APK の作成
libclang_rt.asan-*-android.so
ファイルは NDK のパッケージにあります. jniLibs/<arch>
に入れます.
wrap.sh ファイルは, resources/lib/<arch>
フォルダに入れます(res
でもいいかもしれません)
(jniLibs/<arch>
に置いても, .so ファイルしか APK にコピーされないため)
APK にパッケージングされたら, lib/<arch>/
に .so と wrap.sh が置かれるはずです.
実行時
asan エラーがでると, logcat に
ERROR: AddressSanitizer: SEGV ...
などとエラーとスタックトレースを出してくれます.
ただ, debug ビルドしてもソースコードなどの行は出してくれません.
symbolize
How to Get meaningful stack trace in Android
https://github.com/google/sanitizers/issues/984
スタックのファイル名や行番号を出すには, logcat の結果を, host 側で llvm-symbolizer 走らせて取得する必要があります.
実機で /system/bin/
などに llvm-symbolizer
を入れて動かしたいところですが, 現状ではこれを行うには rooted or ASOP が必要なので, Vulkan/GLES を使うなどグラフィックスメインのアプリ開発では選択肢にはなり得ません.
一応 NDK のパッケージに実デバイスで動く llvm-symbolizer
のリクエストは上がっています.
Add device llvm-symbolizer to NDK
https://github.com/android/ndk/issues/753
TODO
-
logcat で ASAN スタックトレースでソースコードが表示されるようにできないか調べる.
- host で llvm-symbolizer を動かす
-
wrap.sh
で他の .so も有効にする方法を試す(Vulkan validation layers, tsan, msan, etc)