Program sanitarny HWAddress

Android NDK obsługuje HWAddress Sanitizer, czyli HWASan, od wersji NDK r21 i Androida 10 (API na poziomie 29). HWASan jest dostępny tylko na 64-bitowych urządzeniach z architekturą Arm.

HWASan to narzędzie do wykrywania błędów pamięci podobne do ASan. W porównaniu z klasycznym ASan, HWASan ma:

  • Podobny narzut na procesor (ok. 2x)
  • Podobny narzut na rozmiar kodu (40–50%)
  • Znacznie mniejsze obciążenie pamięci RAM (10–35%)

HWASan wykrywa ten sam zestaw błędów co ASan:

  • Przepełnienie lub niedopełnienie bufora stosu i sterty
  • Użycie sterty po zwolnieniu
  • Stosowanie poza zakresem
  • Podwójne bezpłatne lub dzikie bezpłatne

HWASan wykrywa też:

  • Korzystanie z zasobów po zwrocie

Przykładowa aplikacja

Przykładowa aplikacja pokazuje, jak skonfigurować wariant kompilacji dla hwasan.

Koduj

Aby skompilować kod natywny (JNI) aplikacji za pomocą HWAddress Sanitizer, wykonaj te czynności:

ndk-build

W pliku 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 (Gradle Groovy)

W pliku build.gradle modułu:

android {
    defaultConfig {
        externalNativeBuild {
            cmake {
                # Can also use system or none as ANDROID_STL, but not c++_static.
                arguments "-DANDROID_STL=c++_shared"
            }
        }
    }
}

W przypadku każdego celu w pliku CMakeLists.txt:

target_compile_options(${TARGET} PUBLIC -fsanitize=hwaddress -fno-omit-frame-pointer)
target_link_options(${TARGET} PUBLIC -fsanitize=hwaddress)

W NDK w wersji 27 lub nowszej możesz też użyć tych elementów w build.gradle i nie musisz zmieniać pliku CMakeLists.txt:

android {
    defaultConfig {
        externalNativeBuild {
            cmake {
                arguments "-DANDROID_SANITIZE=hwaddress"
            }
        }
    }
}

Nie będzie to działać w przypadku korzystania z ANDROID_USE_LEGACY_TOOLCHAIN_FILE=false.

CMake (Gradle Kotlin)

W pliku build.gradle modułu:

android {
    defaultConfig {
        externalNativeBuild {
            cmake {
                # Can also use system or none as ANDROID_STL, but not c++_static.
                arguments += "-DANDROID_STL=c++_shared"
            }
        }
    }
}

W przypadku każdego celu w pliku CMakeLists.txt:

target_compile_options(${TARGET} PUBLIC -fsanitize=hwaddress -fno-omit-frame-pointer)
target_link_options(${TARGET} PUBLIC -fsanitize=hwaddress)

W NDK w wersji 27 lub nowszej możesz też użyć tych elementów w build.gradle i nie musisz zmieniać pliku CMakeLists.txt:

android {
    defaultConfig {
        externalNativeBuild {
            cmake {
                arguments += "-DANDROID_SANITIZE=hwaddress"
            }
        }
    }
}

Nie będzie to działać w przypadku korzystania z ANDROID_USE_LEGACY_TOOLCHAIN_FILE=false.

Android 14 lub nowszy: dodaj wrap.sh

Jeśli używasz Androida 14 lub nowszego, możesz użyć skryptu wrap.sh, aby uruchomić aplikację z możliwością debugowania na dowolnym urządzeniu z Androidem. Możesz pominąć ten krok, jeśli wykonasz czynności opisane w instrukcjach konfiguracji.

Postępuj zgodnie z instrukcjami, aby spakować skrypt wrap.sh i dodać ten skrypt wrap.sh dla arm64-v8a.

#!/system/bin/sh
LD_HWASAN=1 exec "$@"

Uruchom

Jeśli używasz Androida w wersji starszej niż 14 lub nie dodano skryptu wrap.sh, przed uruchomieniem aplikacji postępuj zgodnie z instrukcjami konfiguracji.

Uruchom aplikację w zwykły sposób. Gdy zostanie wykryty błąd pamięci, aplikacja ulega awarii z sygnałem SIGABRT i wyświetla szczegółowy komunikat w logcat. Kopię wiadomości znajdziesz w pliku w folderze /data/tombstones. Wygląda ona tak:

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)

Po komunikacie mogą pojawić się dodatkowe informacje do debugowania, w tym lista aktywnych wątków w aplikacji, tagi pobliskich alokacji pamięci i wartości rejestrów procesora.

Więcej informacji o komunikatach o błędach HWASan znajdziesz w artykule Interpretowanie raportów HWASan.

Tworzenie plików wykonywalnych wiersza poleceń

Na Androidzie 14 i nowszych możesz tworzyć i uruchamiać pliki wykonywalne z instrumentacją HWASan. W przypadku plików wykonywalnych możesz użyć tej samej konfiguracji, która została opisana w sekcji Kompilowanie w przypadku ndk-build lub CMake. Prześlij pliki wykonywalne na urządzenie z Androidem 14 lub nowszym i uruchom je w normalny sposób za pomocą powłoki.

Jeśli używasz biblioteki libc++, upewnij się, że korzystasz z udostępnionej biblioteki STL, i prześlij ją na urządzenie. Podczas uruchamiania pliku binarnego ustaw LD_LIBRARY_PATH na katalog, w którym się ona znajduje.

Jeśli nie używasz Gradle, zapoznaj się z dokumentacją NDK, aby dowiedzieć się, jak tworzyć kompilacje z wiersza poleceń za pomocą CMakendk-build.

Android 13 lub starszy: konfiguracja

Jeśli na urządzeniu masz Androida 14 lub nowszego, możesz pominąć ten krok i postępować zgodnie z instrukcjami dotyczącymi używania wrap.sh w sekcji Kompilacja. Możesz też przejść do tej sekcji i pominąć instrukcje dotyczące używania skryptu wrap.sh.

Przed Androidem 14 aplikacje HWASan wymagały do działania kompilacji Androida z HWASan. Na obsługiwanych urządzeniach Pixel możesz przeprowadzić aktualizację do gotowych obrazów HWASan. Kompilacje są dostępne na stronie ci.android.com. Możesz tam kliknąć kwadrat odpowiadający kompilacji, którą chcesz pobrać, aby uzyskać link Flash Build. Wymaga to znajomości nazwy kodowej telefonu.

Flashowanie kompilacji urządzenia

Może być łatwiej przejść bezpośrednio na stronę flash.android.com, ponieważ tam proces rozpoczyna się od wykrycia urządzenia i wyświetla tylko kompilacje, których możesz użyć. Poniższe obrazy ilustrują proces konfiguracji w tym narzędziu.

Włącz tryb programisty na urządzeniu i podłącz je do komputera za pomocą kabla USB. Kliknij Dodaj nowe urządzenie, wybierz urządzenie w oknie i kliknij Połącz.

Wykrywanie urządzenia do sflashowania Wybierz urządzenie, z którym chcesz się połączyć.

Po podłączeniu urządzenia kliknij je, aby skonfigurować kompilację. W polu Wybierz identyfikator kompilacji kliknij aosp-master-with-phones-throttledgałąź, aby automatycznie wybrać odpowiedni obraz dla podłączonego urządzenia.

Wybierz urządzenie, które ma migać Potwierdź opcje flashowania i sflashuj urządzenie

Aby wgrać oprogramowanie na urządzenie, kliknij Zainstaluj.

Więcej informacji o konfiguracji znajdziesz w dokumentacji narzędzia Android Flash Tool. Możesz też zapoznać się z dokumentacją AOSP, aby uzyskać instrukcje tworzenia obrazu HWASan ze źródeł.