Cómo interpretar los informes de HWASan

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: '

[...]

[0x00433ae20040,0x00433ae20060) is a small unallocated heap chunk; size: 32 offset: 5








[ … 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 con WRITE)
  • 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):

  1. La lista de subprocesos en el proceso
  2. La lista de subprocesos en el proceso
  3. El valor de las etiquetas de memoria cerca de la memoria con errores
  4. 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.