Cuando la herramienta HWASan detecta un error de memoria, el proceso se finaliza con abort()
y se imprime un informe en stderr y logcat. Al igual que todos los errores nativos en Android, los errores de HWASan están debajo de /data/tombstones
.
Informe de ejemplo
En comparación con las fallas nativas normales, HWASan lleva información adicional en el campo Abort message cerca de la parte superior de la lápida. Este es un ejemplo de falla basada en un montón. Para ver los errores de pila, consulta la nota de las secciones específicas de la pila.
*** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** Build fingerprint: 'google/flame_hwasan/flame:Tiramisu/MASTER/7956676:userdebug/dev-keys' Revision: 'DVT1.0' ABI: 'arm64' Timestamp: 2019-04-24 01:13:22+0000 pid: 11154, tid: 11154, name: sensors@1.0-ser >>> /vendor/bin/hw/android.hardware.sensors@1.0-service <<< signal 6 (SIGABRT), code -1 (SI_QUEUE), fault addr -------- Abort message: '==9569==ERROR: HWAddressSanitizer: tag-mismatch on address 0x00433ae20045 at pc 0x00623ae2a9cc READ of size 1 at 0x00433ae20045 tags: 5b/83 (ptr/mem) in thread T0 #0 0x7240450c68 (/system/lib64/vndk-sp-R/libcutils.so+0x8c68) #1 0x723dffd490 (/vendor/lib64/sensors.ssc.so+0x34490) #2 0x723e0126e0 (/vendor/lib64/sensors.ssc.so+0x496e0) [...] [0x00433ae20040,0x00433ae20060) is a small unallocated heap chunk; size: 32 offset: 5 Cause: use-after-free 0x00433ae20045 is located 5 bytes inside of 10-byte region [0x00433ae20040,0x00433ae2004a) freed by thread T0 here: #0 0x72404d1b18 (/system/lib64/libclang_rt.hwasan-aarch64-android.so+0x10b18) #1 0x723af23040 (/vendor/lib64/libgralloccore.so+0x5040) #2 0x723af23fa4 (/vendor/lib64/libgralloccore.so+0x5fa4) [...] previously allocated here: #0 0x72404ce554 (/system/lib64/libclang_rt.hwasan-aarch64-android.so+0xd554) #1 0x7240115654 (/apex/com.android.runtime/lib64/bionic/libc.so+0x43654) #2 0x7240450ac8 (/system/lib64/vndk-sp-R/libcutils.so+0x8ac8) [...] hwasan_dev_note_heap_rb_distance: 1 1023 hwasan_dev_note_num_matching_addrs: 0 hwasan_dev_note_num_matching_addrs_4b: 0 Thread: T0 0x006a00002000 stack: [0x007fc1064000,0x007fc1864000) sz: 8388608 tls: [0x00737702ffc0,0x007377033000) Memory tags around the buggy address (one tag corresponds to 16 bytes): 0x006f33ae1f80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x006f33ae1f90: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x006f33ae1fa0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x006f33ae1fb0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x006f33ae1fc0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x006f33ae1fd0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x006f33ae1fe0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x006f33ae1ff0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 =>0x006f33ae2000: 08 00 08 00 [83] 00 00 00 00 00 00 00 00 00 00 00 0x006f33ae2010: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x006f33ae2020: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x006f33ae2030: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x006f33ae2040: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x006f33ae2050: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x006f33ae2060: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x006f33ae2070: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x006f33ae2080: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 Tags for short granules around the buggy address (one tag corresponds to 16 bytes): 0x006f33ae1ff0: .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. =>0x006f33ae2000: 72 .. d0 .. [..] .. .. .. .. .. .. .. .. .. .. .. 0x006f33ae2010: .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. See https://clang.llvm.org/docs/HardwareAssistedAddressSanitizerDesign.html#short-granules for a description of short granule tags Registers where the failure occurred (pc 0x00623ae2a9cc): x0 0000007fc18623ec x1 5b0000433ae20045 x2 0000000000000013 x3 ffffffffffffffff x4 ffffffffffffffff x5 0000007fc1861da3 x6 6f7420676e696f47 x7 45522061206f6420 x8 0000000000000000 x9 0200006b00000000 x10 00000007fc18623f x11 5b0000433ae20040 x12 6f64206f7420676e x13 0a44414552206120 x14 0000000000000010 x15 ffffffffffffffff x16 000000737169ac94 x17 0000000000000007 x18 0000007377bd8000 x19 0000007fc1862498 x20 0200006b00000000 x21 0000007fc18624a8 x22 0000000000000001 x23 0000000000000000 x24 0000000000000000 x25 0000000000000000 x26 0000000000000000 x27 0000000000000000 x28 0000000000000000 x29 0000007fc1862410 x30 000000623ae2a9d0 sp 0000007fc18623d0 SUMMARY: HWAddressSanitizer: tag-mismatch (/system/lib64/vndk-sp-R/libcutils.so+0x8c68) [ … regular crash dump follows …]
Esto es similar a un informe de AddressSanitizer. A diferencia de esos, casi todos los errores de HWASan son errores de discrepancia de etiquetas, es decir, un acceso a la memoria en el que una etiqueta de puntero no coincide con la etiqueta de memoria correspondiente. Puede ser cualquiera de las siguientes opciones:
- Acceso fuera de los límites en la pila o el montón
- Error de uso después de la liberación en el montón
- Error de uso después de la devolución en la pila
Secciones
A continuación, se explica cada una de las secciones del informe HWASan.
Error de acceso
Contiene información sobre el acceso a memoria defectuosa, lo que incluye lo siguiente:
- Tipo de acceso (
READ
en comparación conWRITE
) - Tamaño de acceso (cuántos bytes se intentaron acceder)
- Número de subproceso del acceso
- Etiquetas de puntero y memoria (para depuración avanzada)
Cómo acceder al seguimiento de pila
Seguimiento de pila del acceso incorrecto a la memoria. Consulta Simbolización para obtener información sobre cómo simbolizar.
Causa
La posible causa del acceso incorrecto. Si hay varios candidatos, se enumeran en orden de probabilidad descendente. Precede a la información detallada sobre la posible causa. HWASan puede diagnosticar las siguientes causas:
- Uso después de la liberación
- No coincidencia de etiquetas de pila, que puede ser uso de pila después de la devolución, uso de pila después del alcance o fuera de los límites
- Desbordamiento del búfer del montón
- Ampliación global
Información de la memoria
Describe lo que HWASan sabe sobre la memoria a la que se accede y puede diferir según el tipo de error:
Tipo de error | Causa | Formato del informe |
---|---|---|
Discrepancia de etiquetas | Uso después de la liberación | Usa el siguiente formato de informe:<address> is located N bytes inside of M-byte region [<start>, <end>) freed by thread T0 here: |
Desbordamiento del búfer del montón | Ten en cuenta que esto también puede ser un desbordamiento negativo.<address> is located N bytes to the right of M-byte region [<start>, <end>) allocated here: |
|
La etiqueta de pila no coincide | Los informes de pila no diferencian entre desbordamientos o subdesbordamientos y errores de uso después de la devolución. Además, para encontrar la asignación de pila que es la fuente del error, se requiere un paso de simbolización sin conexión. Consulta Información sobre los informes de pila. | |
Tiempo libre no válido | Uso después de la liberación | Un error de liberación doble. Si esto sucede cuando se cierra el proceso, puede significar un incumplimiento de la ODR.
<address> is located N bytes inside of M-byte region [<start>, <end>) freed by thread T0 here: |
No se puede describir la dirección | Ya sea una liberación no controlada (liberación de memoria que no se había asignado antes) o una liberación doble después de que la memoria asignada se desalojó del búfer libre de HWASan. | |
0x… es la memoria en sombra de HWAsan. | Un error de liberación no controlada, ya que la app intentaba liberar memoria interna de HWASan. |
Seguimiento de pila de desasignación
Seguimiento de pila de donde se desasignó la memoria. Solo está presente para errores de uso después de la liberación o de uso no válido. Consulta Simbolización para simbolizar.
Seguimiento de pila de asignación
Es el seguimiento de pila del lugar en el que se asignó la memoria. Consulta Simbolización para simbolizar.
Información de depuración avanzada
El informe de HWASan también incluye información de depuración avanzada, como la siguiente (en orden):
- La lista de subprocesos en el proceso
- La lista de subprocesos en el proceso
- El valor de las etiquetas de memoria cerca de la memoria con errores
- El volcado de los registros en el punto de acceso a la memoria
Volcado de etiquetas de memoria
Puedes usar el volcado de memoria de etiquetas para buscar asignaciones de memoria cercanas con la misma etiqueta que la etiqueta del puntero. Estas etiquetas pueden indicar un acceso fuera de los límites con un gran desplazamiento. Una etiqueta corresponde a 16 bytes de memoria; la etiqueta del puntero son los 8 bits superiores de la dirección. El volcado de memoria de la etiqueta puede proporcionar sugerencias. Por ejemplo, el siguiente es un desbordamiento de búfer a la derecha:
tags: ad/5c (ptr/mem) [...] Memory tags around the buggy address (one tag corresponds to 16 bytes): 0x006f33ae1ff0: 0e 0e 0e 57 20 20 20 20 20 2e 5e 5e 5e 5e 5e b5 =>0x006f33ae2000: f6 f6 f6 f6 f6 4c ad ad ad ad ad ad [5c] 5c 5c 5c 0x006f33ae2010: 5c 04 2e 2e 2e 2e 2e 2f 66 66 66 66 66 80 6a 6a Tags for short granules around the buggy address (one tag corresponds to 16 bytes): 0x006f33ae1ff0: ab 52 eb .. .. .. .. .. .. .. .. .. .. .. .. .. =>0x006f33ae2000: .. .. .. .. .. .. .. .. .. .. .. .. [..] .. .. .. 0x006f33ae2010: .. 5c .. .. .. .. .. .. .. .. .. .. .. .. .. ..
Observa la ejecución de 6 × 16 = 96 bytes de etiquetas ad
a la izquierda que coinciden con la etiqueta del puntero.
Si el tamaño de una asignación no es un múltiplo de 16, el resto del tamaño se almacena como la etiqueta de memoria y la etiqueta se almacena como una etiqueta de gránulo corto. En el ejemplo anterior, justo después de la asignación en negrita etiquetada como ad
, tenemos una asignación de 5 × 16 + 4 = 84 bytes de la etiqueta 5c
.
Una etiqueta de memoria cero (por ejemplo, tags: ad/00 (ptr/mem)
) indica un error de uso de pila después del retorno.
Volcado de registro
El volcado de registro en los informes de HWASan corresponde a la instrucción que realizó el acceso a la memoria no válido. A este volcado le sigue otro volcado de registro del controlador de señales normal de Android. Ignora el segundo volcado, ya que se tomó cuando HWASan llamó a abort()
y no es relevante para el error.
Simbolización
Para obtener los nombres de las funciones y los números de línea en los seguimientos de pila (y obtener nombres de variables para errores de uso después del alcance), se necesita un paso de simbolización sin conexión.
Configuración inicial: Instala llvm-symbolizer
Para simbolizar, tu sistema debe tener instalado llvm-symbolizer
y se debe poder acceder a él desde $PATH
. En Debian, puedes instalarlo con sudo apt install llvm
.
Obtén archivos de símbolos
Para la simbolización, requerimos objetos binarios sin quitar símbolos que contengan símbolos. Su ubicación depende del tipo de compilación:
- Para las compilaciones locales, los archivos de símbolos están en
out/target/product/<product>/symbols/
. - En el caso de las compilaciones de AOSP (por ejemplo, las que se escriben en la memoria flash desde Android Flash Tool), las compilaciones están en Android CI. En Artefactos para la compilación, hay un archivo
${PRODUCT}-symbols-${BUILDID}.zip
. - Para las compilaciones internas de tu organización, consulta la documentación de tu organización para obtener ayuda para obtener archivos de símbolos.
Simbolizar
hwasan_symbolize --symbols <DECOMPRESSED_DIR>/out/target/product/*/symbols < crash
Comprende los informes de pila
En el caso de los errores que se producen con las variables de pila, el informe de HWASan contiene detalles como los siguientes:
Cause: stack tag-mismatch Address 0x007d4d251e80 is located in stack of thread T64 Thread: T64 0x0074000b2000 stack: [0x007d4d14c000,0x007d4d255cb0) sz: 1088688 tls: [0x007d4d255fc0,0x007d4d259000) Previously allocated frames: record_addr:0x7df7300c98 record:0x51ef007df3f70fb0 (/apex/com.android.art/lib64/libart.so+0x570fb0) record_addr:0x7df7300c90 record:0x5200007df3cdab74 (/apex/com.android.art/lib64/libart.so+0x2dab74) [...]
Para ayudarte a comprender los errores de pila, HWASan realiza un seguimiento de los marcos de pila anteriores. HWASan no los transforma en contenido comprensible por humanos en el informe de errores y requiere un paso de simbolización adicional.
Incumplimientos de la ODR
Algunos errores de uso después de la liberación que informa HWASan pueden indicar un incumplimiento de la regla de una definición (ODR). Se produce una infracción de la ODR cuando se define la misma variable varias veces en el mismo programa. Esto también significa que la variable se destruye varias veces, lo que puede generar el error de uso después de la liberación.
Después de la simbolización, las infracciones de ODR muestran un error de uso después de la liberación con __cxa_finalize
,
en la pila de acceso no válida y en la pila liberada aquí. La pila asignada anteriormente aquí contiene __dl__ZN6soinfo17call_constructorsEv
y debería apuntar a la ubicación de tu programa que define la variable más alta en la pila.
Se puede incumplir la ODR si se usan bibliotecas estáticas. Si una biblioteca estática que define un elemento global de C++ está vinculada a varias bibliotecas compartidas o ejecutables, es posible que existan varias definiciones del mismo símbolo en el mismo espacio de direcciones, lo que genera un error de ODR.
Solución de problemas
En esta sección, se describen algunos errores y cómo abordarlos.
HWAddressSanitizer no puede describir la dirección con más detalle
A veces, HWASan puede quedarse sin espacio para la información sobre las asignaciones de memoria anteriores. En ese caso, el informe solo contiene un seguimiento de pila para el acceso inmediato a la memoria, seguido de una nota:
HWAddressSanitizer can not describe address in more detail.
En algunos casos, puedes resolver este problema ejecutando la prueba varias veces. Otra opción es
aumentar el tamaño del historial de HWASan. Puedes hacerlo de forma global en
build/soong/cc/sanitize.go
(busca
hwasanGlobalOptions
) o en tu entorno de proceso (prueba
adb shell echo $HWASAN_OPTIONS
para ver la configuración actual).
Este error también puede ocurrir si la memoria a la que se accedió no está asignada o si un asignador que no es compatible con HWASan la asignó. En este caso, la etiqueta mem
que se indica en el encabezado de falla suele ser 00
. Si tienes acceso a la lápida completa, puede ser útil consultar el volcado de mapas de memoria para averiguar a qué asignación (si la hay) pertenece la dirección.
Error anidado en el mismo subproceso
Esto significa que hubo un error cuando se generaba el informe de fallas de HWASan. Por lo general, esto se debe a un error en el entorno de ejecución de HWASan. Informa un error y proporciona instrucciones para reproducirlo, si es posible.