HWAddress Sanitizer

El NDK de Android admite HWAddress Sanitizer, también conocido como HWASan, a partir de la versión r21 de NDK y Android 10 (nivel de API 29). HWASan solo está disponible en dispositivos ARM de 64 bits.

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 las siguientes características:

  • Sobrecarga de la CPU similar (alrededor de 2 veces más)
  • 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 o desbordamiento del búfer de pila y montón
  • Uso de montón después de liberación
  • Uso de pila fuera del alcance
  • Liberación doble o salvaje

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

  • Uso de pila después de mostrar

App de ejemplo

En una app de ejemplo, se muestra cómo configurar una variante de compilación para HWASan.

Compilación

Para compilar el código nativo (JNI) de la 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)
target_link_options(${TARGET} PUBLIC -fsanitize=hwaddress)

Con el NDK 27 o versiones posteriores, también puedes usar lo siguiente en tu build.gradle y no tienes que cambiar CMakeLists.txt:

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

Esto no funcionará cuando se use ANDROID_USE_LEGACY_TOOLCHAIN_FILE=false.

Android 14 o versiones posteriores: agrega wrap.sh

Si ejecutas Android 14 o versiones posteriores, puedes usar una secuencia de comandos wrap.sh para ejecutar la app depurable en cualquier dispositivo Android. Puedes omitir este paso si eliges seguir los pasos de las Instrucciones de configuración.

Sigue las instrucciones para empaquetar una secuencia de comandos wrap.sh y agregar la siguiente secuencia de comandos wrap.sh para arm64-v8a.

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

Ejecutar

Si ejecutas una versión de Android anterior a la 14 o no agregaste una secuencia de comandos wrap.sh, sigue las instrucciones de configuración antes de ejecutar la app.

Ejecuta la app como de costumbre. 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 dentro de /data/tombstones que se ve 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)

Es posible que el mensaje esté seguido de información de depuración adicional, como la lista de subprocesos activos de la aplicación, etiquetas de asignaciones de memoria cercanas y valores de registro de la CPU.

Consulta Cómo interpretar los informes de HWASan para obtener más información sobre los mensajes de error de HWASan.

Cómo compilar ejecutables de línea de comandos

Puedes compilar y ejecutar ejecutables instrumentados con HWASan en Android 14 y versiones posteriores. Puedes usar la misma configuración que se describe en Compilación para ndk-build o CMake para tus ejecutables. Envía los ejecutables a un dispositivo con Android 14 o versiones posteriores y ejecútalos como de costumbre con la shell.

Si usas libc++, asegúrate de usar la STL compartida y envíala al dispositivo. Luego, configura LD_LIBRARY_PATH en el directorio que la contiene cuando ejecutes el objeto binario.

Si no usas Gradle, consulta la documentación del NDK para aprender a compilar desde la línea de comandos con CMake y ndk-build.

Android 13 o versiones anteriores: configuración

Si tu dispositivo ejecuta Android 14 o versiones posteriores, puedes omitir este paso y seguir las instrucciones para usar wrap.sh en la sección Compilación. También puedes seguir esta sección y omitir las instrucciones de uso de wrap.sh.

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

Escribe en la memoria flash una compilación del dispositivo

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. En las siguientes imágenes, se muestra el flujo de configuración en esta herramienta.

Habilita el modo de desarrollador en el dispositivo y luego conecta ese dispositivo a la computadora con un cable USB. Haz clic en Agregar nuevo dispositivo, selecciona tu dispositivo en el diálogo y haz clic en Conectar.

Detecta un dispositivo para realizar la instalación Selecciona el dispositivo al que deseas conectarte

Una vez que el dispositivo esté conectado, haz clic en él para configurar la compilación. En el cuadro donde seleccionas un ID de compilación, elige la rama aosp-master-with-phones-throttled para que se seleccione automáticamente la imagen correcta del dispositivo que conectaste.

Selecciona un dispositivo para realizar la instalación Confirma las opciones y luego instala la compilación en el dispositivo

Haz clic en Instalar para instalar la compilación en el dispositivo.

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.