Quando a ferramenta HWASan detecta um bug de memória, o processo é encerrado com abort()
,
e um relatório é impresso no stderr e no Logcat. Como todos os travamentos nativos no Android, os erros do HWASan estão
em /data/tombstones
.
Exemplo de relatório
Em comparação com falhas nativas normais, o HWASan tem informações extras no campo Mensagem de interrupção, perto da parte de cima da lápide. Confira um exemplo de falha baseada em heap. Para bugs de pilha, consulte a nota sobre as seções específicas de pilha.
*** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** 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 …]
Isso é semelhante a um relatório do AddressSanitizer. Ao contrário desses, quase todos os bugs do HWASan são erros de incompatibilidade de tag, ou seja, um acesso à memória em que uma tag de ponteiro não corresponde à tag de memória correspondente. Isso pode ser um dos seguintes motivos:
- Acesso fora dos limites na pilha ou na pilha de heap
- Erro de uso após liberação no heap
- Erro de uso após o retorno na pilha
Seções
Confira a explicação de cada uma das seções do relatório HWASan.
Erro de acesso
Contém informações sobre o acesso incorreto à memória, incluindo:
- Tipo de acesso (
READ
versusWRITE
) - Tamanho de acesso (quantos bytes foram acessados)
- Número da linha de execução do acesso
- Tags de ponteiro e de memória (para depuração avançada)
Acesso ao stack trace
Stack trace do acesso de memória inválido. Consulte Simbologia para saber como simbolizar.
Causa
A possível causa do acesso indevido. Se houver vários candidatos, eles serão listados em ordem de probabilidade decrescente. Antecede as informações detalhadas sobre a possível causa. O HWASan pode diagnosticar as seguintes causas:
- Use After Free
- Incompatibilidade de tag de pilha, que pode ser uso de pilha após retorno, uso de pilha após escopo ou fora dos limites
- Estouro de buffer de heap
- Transbordamento global
Informações de memória
Descreve o que o HWASan sabe sobre a memória que está sendo acessada e pode variar de acordo com o tipo de bug:
Tipo de bug | Causa | Formato do relatório |
---|---|---|
Incompatibilidade de tags | Use After Free | Use este formato de relatório:<address> is located N bytes inside of M-byte region [<start>, <end>) freed by thread T0 here: |
Estouro de buffer de heap | Isso também pode ser um underflow.<address> is located N bytes to the right of M-byte region [<start>, <end>) allocated here: |
|
Tag de pilha incompatível | Os relatórios de pilha não diferenciam overflow ou underflow e bugs de uso após o retorno. Além disso, para encontrar a alocação de pilha que é a origem do erro, é necessária uma etapa de simbolização off-line. Consulte Noções básicas sobre relatórios de pilha. | |
Liberação inválida | Use After Free | Um bug de double free. Se isso acontecer no encerramento do processo, pode indicar uma
violação de ODR.
<address> is located N bytes inside of M-byte region [<start>, <end>) freed by thread T0 here: |
Não é possível descrever o endereço | Ou um free selvagem (livre de memória que não foi alocada antes) ou um double free depois que a memória alocada foi removida do buffer livre do HWASan. | |
0x... é a memória sombra do HWAsan | Um wild free, porque o app estava tentando liberar memória interna do HWASan. |
Stack trace de desalocação
Stack trace de onde a memória foi desalocada. Apresentado apenas para bugs de uso após a liberação ou bugs de invalid-free. Consulte Simbologia para saber mais.
Stack trace de alocação
Stack trace de onde a memória foi alocada. Consulte Simbologia para saber mais.
Informações avançadas de depuração
O relatório do HWASan também apresenta algumas informações avançadas de depuração, incluindo:
- A lista de linhas de execução no processo
- A lista de linhas de execução no processo
- O valor das tags de memória perto da memória com falha
- O despejo dos registros no ponto de acesso à memória
Despejo de tag de memória
É possível usar o despejo de memória de tag para procurar alocações de memória próximas com a mesma tag que a tag do ponteiro. Essas tags podem apontar para um acesso fora dos limites com um deslocamento grande. Uma tag corresponde a 16 bytes de memória. A tag do ponteiro é os 8 bits principais do endereço. O dump de memória de tags pode dar dicas. Por exemplo, o seguinte é um buffer overflow à direita:
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 .. .. .. .. .. .. .. .. .. .. .. .. .. ..
Observe a execução de 6 × 16 = 96 bytes de tags ad
à esquerda que correspondem à
tag do ponteiro.
Se o tamanho de uma alocação não for um múltiplo de 16, o restante do tamanho será armazenado como a
tag de memória e a tag será armazenada como uma tag de
granulo curto. No exemplo anterior, logo após a alocação em negrito marcada
ad
, temos uma alocação de 5 × 16 + 4 = 84 bytes da tag 5c
.
Uma tag de memória zero (por exemplo, tags: ad/00 (ptr/mem)
) indica um
bug de uso da pilha após o retorno.
Registro de despejo
O despejo de registro nos relatórios do HWASan corresponde à instrução que executou o
acesso à memória inválido. Esse dump é seguido por outro dump de registro do gerenciador de sinais
regular do Android. Ignore o segundo despejo, porque ele foi feito quando o HWASan chamou
abort()
e não é relevante para o bug.
Simbolização
Para conferir os nomes de função e os números de linha em stack traces e conferir os nomes de variáveis para bugs de uso após o escopo, é necessária uma etapa de simbolização off-line.
Configuração inicial: instale o llvm-symbolizer
Para simbolizar, seu sistema precisa ter o llvm-symbolizer
instalado e acessível em
$PATH
. No Debian, é possível instalar usando sudo apt install llvm
.
Conseguir arquivos de símbolo
Para a simbolização, são necessários binários não simplificados que contenham símbolos. A localização depende do tipo de build:
- Para builds locais, os arquivos de símbolo estão em
out/target/product/<product>/symbols/
. - Para builds do AOSP (por exemplo, atualizados pela
Android Flash Tool), os
builds estão no Android CI. Nos Artefatos
do build, há um arquivo
${PRODUCT}-symbols-${BUILDID}.zip
. - Para builds internos da sua organização, consulte a documentação da organização para saber como acessar os arquivos de símbolo.
Simbolizar
hwasan_symbolize --symbols <DECOMPRESSED_DIR>/out/target/product/*/symbols < crash
Entender os relatórios de pilha
Para bugs que ocorrem com variáveis de pilha, o relatório do HWASan contém detalhes como estes:
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 ajudar a entender os bugs de pilha, o HWASan rastreia os frames de pilha anteriores. O HWASan não transforma esses dados em conteúdo compreensível para humanos no relatório de bug e requer uma etapa de simbolização extra.
Violações de ODR
Alguns bugs de uso após a liberação relatados pelo HWASan podem indicar uma violação da regra de definição única (ODR, na sigla em inglês). Uma violação de ODR acontece quando a mesma variável é definida várias vezes no mesmo programa. Isso também significa que a variável é destruída várias vezes, o que pode levar ao uso de um erro de uso após a liberação.
Após a simbolização, as violações de ODR mostram um erro de uso após a liberação com __cxa_finalize
,
tanto na pilha de acesso inválido quanto na freed here. A pilha alocada
anteriormente aqui contém __dl__ZN6soinfo17call_constructorsEv
e deve
apontar para o local no programa que define a variável mais alta na pilha.
O ODR pode ser violado se bibliotecas estáticas forem usadas. Se uma biblioteca estática que define um global C++ for vinculada a várias bibliotecas compartilhadas ou executáveis, várias definições do mesmo símbolo poderão existir no mesmo espaço de endereço, o que causa um erro de ODR.
Solução de problemas
Esta seção descreve alguns erros e como resolvê-los.
O HWAddressSanitizer não pode descrever o endereço com mais detalhes
Às vezes, o HWASan pode ficar sem espaço para informações sobre alocações de memória anteriores. Nesse caso, o relatório contém apenas um stack trace para o acesso imediato à memória, seguido por uma observação:
HWAddressSanitizer can not describe address in more detail.
Em alguns casos, é possível resolver esse problema executando o teste várias vezes. Outra opção é
aumentar o tamanho do histórico do HWASan. Isso pode ser feito globalmente em
build/soong/cc/sanitize.go
(procure por
hwasanGlobalOptions
) ou no ambiente de processo (tente
adb shell echo $HWASAN_OPTIONS
para ver as configurações atuais).
Esse erro também pode acontecer se a memória acessada não for mapeada ou alocada por um alocador compatível
com o HWASan. Nesse caso, a tag mem
listada no cabeçalho do crash geralmente é
00
. Se você tiver acesso ao tombstone completo, consulte o
dump de mapas de memória para descobrir a qual mapeamento (se houver) o endereço pertence.
Bug aninhado na mesma linha de execução
Isso significa que houve um bug ao gerar o relatório de falha do HWASan. Isso geralmente ocorre devido a um bug no ambiente de execução do HWASan. Registre um bug e forneça instruções sobre como reproduzir o problema, se possível.