HWAddress Sanitizer

El NDK de Android admite HWAddress Sanitizer a partir de NDK r21 y Android 10 (API nivel 29).

HWASan es una herramienta de detección de errores de memoria similar a ASan. En comparación con la versión clásica de ASan, HWASan tiene lo siguiente:

  • Sobrecarga de la CPU similar (~2x)
  • Sobrecarga del tamaño de código similar (del 40 al 50%)
  • Sobrecarga de la RAM mucho menor (del 10 al 35%)

HWASan detecta el mismo conjunto de errores que ASan:

  • Desabastecimiento de búfer de pila
  • Uso de pila después de liberación
  • Uso de pila fuera del alcance
  • Cierre doble o cierre wild

Además, HWASan también detecta lo siguiente:

  • Uso de pila después de mostrar

Cómo configurar

Las aplicaciones HWASan necesitan una compilación HWASan de Android para ejecutarse. Puedes instalar imágenes HWASan compiladas previamente en dispositivos Pixel compatibles. Las compilaciones están disponibles en ci.android.com. Allí, puedes hacer clic en la compilación exacta de la que deseas obtener el vínculo para instalarla. Es necesario que conozcas el nombre interno de tu teléfono.

Quizás sea más fácil visitar directamente flash.android.com, ya que allí el flujo comienza con la detección de tu dispositivo y solo muestra las compilaciones que puedes usar. Tendrás que elegir la rama aosp-master-with-phones-throttled del cuadro combinado de la izquierda, pero esa acción elegirá automáticamente la imagen correcta para el dispositivo que hayas conectado. Puedes encontrar más información sobre la configuración necesaria en la documentación de Android Flash Tool.

También puedes consultar la documentación de AOSP para obtener instrucciones sobre cómo compilar una imagen de HWASan desde la fuente.

Cómo compilar

Para compilar el código nativo (JNI) de tu app con HWAddress Sanitizer, haz lo siguiente:

ndk-build

En el archivo Application.mk, incluye lo siguiente:

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

En el archivo build.gradle de tu módulo, incluye lo siguiente:

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

Para cada destino de tu CMakeLists.txt:

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

Cómo ejecutar

Ejecuta la app como de costumbre en una imagen de Android compilada con HWASan. Cuando se detectan errores de memoria, las apps muestran una falla de SIGABRT y registran un mensaje detallado en logcat. Puedes encontrar una copia del mensaje en un archivo en /data/tombstones y se verá de la siguiente manera:

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)
    

El mensaje puede ir seguido de información de depuración adicional, como la lista de subprocesos activos de la aplicación, etiquetas de asignaciones de memoria cercanas, valores de registro de CPU, etcétera.