Quando a ferramenta HWASan detecta um bug de memória, o processo é encerrado com abort() e um relatório é impresso em stderr e logcat. Como todas as falhas nativas no Android, os erros HWASan podem ser encontrados em /data/tombstones
.
Em comparação com as falhas nativas regulares, o HWASan carrega informações extras no campo “Abort message” próximo ao topo da lápide. Veja um exemplo de falha baseada em heap abaixo (para bugs de pilha, veja a nota abaixo para as seções específicas da pilha).
Exemplo de relatório
*** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** 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 é muito semelhante a um relatório AddressSanitizer . Ao contrário desses, quase todos os bugs do HWASan são “tag-mismatch”, ou seja, um acesso à memória onde uma tag de ponteiro não corresponde à tag de memória correspondente. Este pode ser um dos
- acesso fora dos limites na pilha ou heap
- usar depois de livre na pilha
- usar após retornar à pilha
Seções
Uma explicação de cada uma das seções do relatório HWASan está abaixo:
Erro de acesso
Contém informações sobre o acesso incorreto à memória, incluindo:
- Tipo de acesso ("READ" vs. "WRITE")
- Tamanho do acesso (quantos bytes foram tentados para serem acessados)
- Número da linha de acesso
- Tags de ponteiro e memória (para depuração avançada)
Acessar rastreamento de pilha
Rastreamento de pilha do acesso incorreto à memória. Veja a seção Simbologia para simbolizar.
Causa
A causa potencial para o mau acesso. Se houver vários candidatos, eles serão listados em ordem decrescente de probabilidade. Precede as informações detalhadas sobre a causa potencial. HWASan pode diagnosticar as seguintes causas:
- use-after-free
- stack tag-mismatch: pode ser uso após retorno / uso após escopo ou fora dos limites
- estouro de buffer de heap
- transbordamento global
Informação de memória
Descreve o que o HWASan sabe sobre a memória que está sendo acessada e pode diferir com base no tipo de bug.
Tipo de Inseto | Causa | Formato do relatório |
---|---|---|
tag incompatível | use-after-free | <address> is located N bytes inside of M-byte region [<start>, <end>) freed by thread T0 here: |
estouro de buffer de heap | Observe que isso também pode ser um underflow.<address> is located N bytes to the right of M-byte region [<start>, <end>) allocated here: | |
incompatibilidade de tag de pilha | Os relatórios de pilha não diferenciam entre erros de estouro/subfluxo e erros de uso após retorno. Além disso, para encontrar a alocação da pilha que é a origem do erro, é necessária uma etapa de simbolização off-line. Consulte a seção Entendendo os relatórios de pilha abaixo. | |
livre de inválidos | use-after-free | Este é um bug gratuito duplo. Se isso acontecer no encerramento do processo, isso pode significar uma violação de ODR .<address> is located N bytes inside of M-byte region [<start>, <end>) freed by thread T0 here: |
não pode descrever o endereço | Um wild free (livre de memória que não havia sido alocada antes) ou um double free após a memória alocada ter sido removida do buffer livre do HWASan. | |
0x… é uma memória de sombra HWA. | Este é definitivamente um livre selvagem, pois o aplicativo estava tentando liberar a memória interna do HWASan. |
Rastreamento de Pilha de Desalocação
Rastreamento de pilha de onde a memória foi desalocada. Presente apenas para bugs livres de uso ou livres de inválidos. Veja a seção Simbologia para simbolizar.
Rastreamento de Pilha de Alocação
Rastreamento de pilha de onde a memória foi alocada. Veja a seção Simbologia para simbolizar.
Informações avançadas de depuração
O relatório HWASan também apresenta algumas informações avançadas de depuração, incluindo (em ordem):
- A lista de threads no processo
- A lista de threads no processo
- O valor dos tags de memória perto da memória com falha
- O despejo dos registradores no ponto de acesso à memória
Despejo de Marca de Memória
O despejo de memória do tag pode ser usado para procurar alocações de memória próximas com o mesmo tag que o tag do ponteiro. Isso pode apontar para um acesso fora dos limites com um grande deslocamento. Um tag corresponde a 16 bytes de memória; a tag do ponteiro são os 8 bits superiores do endereço. O despejo de memória do tag pode fornecer dicas, por exemplo, o seguinte é um estouro de buffer à 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 de ponteiro).
Se o tamanho de uma alocação não for um múltiplo de 16, o restante do tamanho será armazenado como etiqueta de memória e a etiqueta será armazenada como uma etiqueta de granulado curto . No exemplo acima, logo após o anúncio marcado com alocação em negrito, temos uma alocação de 5 × 16 + 4 = 84 bytes da tag 5c.
Uma tag de memória zero (ex. tags: ad/ 00 (ptr/mem)
) geralmente indica um bug de uso após retorno da pilha.
Registrar Despejo
O despejo de registro nos relatórios HWASan corresponde à instrução real que executou o acesso inválido à memória. Ele é seguido por outro despejo de registro do manipulador de sinal regular do Android - ignore o segundo , é obtido quando HWASan chamou abort() e não é relevante para o bug.
simbolização
Para obter nomes de função e números de linha em rastreamentos de pilha (e obter nomes de variáveis para bugs de uso após o escopo), é necessária uma etapa de simbolização offline.
Configuração inicial: instale o llvm-symbolizer
Para simbolizar, seu sistema deve ter o llvm-symbolizer instalado e acessível a partir de $PATH. No Debian, você pode instalá-lo usando sudo apt install llvm
.
Obter arquivos de símbolo
Para simbolização, exigimos binários não despojados contendo símbolos. Onde eles podem ser encontrados depende do tipo de construção:
Para compilações locais , os arquivos de símbolo podem ser encontrados em out/target/product/<product>/symbols/
.
Para compilações AOSP (por exemplo, flash do Flashstation ), as compilações podem ser encontradas no Android CI . Nos "Artifacts" para a compilação, haverá um arquivo `${PRODUCT}-symbols-${BUILDID}.zip`.
Para compilações internas de sua organização, verifique a documentação de sua organização para obter ajuda na obtenção de arquivos de símbolos.
Simbolizar
hwasan_symbolize –-symbols <DECOMPRESSED_DIR>/out/target/product/*/symbols < crash
Noções básicas sobre relatórios de pilha
Para bugs que ocorrem com variáveis de pilha, o relatório HWASan conterá detalhes como este:
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 permitir que os bugs de pilha sejam compreendidos, o HWASan acompanha os quadros de pilha que aconteceram no passado. Atualmente, o HWASan não transforma isso em conteúdo compreensível por humanos no relatório de bug e requer uma etapa de simbolização adicional .
Violações de ODR
Alguns erros de uso após a liberação relatados pelo HWASan também podem indicar uma violação da regra de definição única (ODR). Uma violação de ODR ocorre 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 erro use-after-free.
Após a simbolização, as violações de ODR mostram um use-after-free com __cxa_finalize
, tanto na pilha de acesso inválido quanto na pilha "freed here". A pilha "anteriormente alocada aqui" contém __dl__ZN6soinfo17call_constructorsEv
e deve apontar para o local em seu programa que define a variável mais alta na pilha.
Uma razão pela qual o ODR pode ser violado é quando bibliotecas estáticas são usadas. Se uma biblioteca estática que define um C++ global estiver vinculada a várias bibliotecas compartilhadas ou executáveis, várias definições do mesmo símbolo podem acabar existindo no mesmo espaço de endereço, o que causará um erro de ODR.
Solução de problemas
"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 conterá apenas um rastreamento de pilha para o acesso imediato à memória, seguido de uma observação:
HWAddressSanitizer can not describe address in more detail.
Em alguns casos, isso pode ser resolvido 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 em seu ambiente de processo (tente adb shell echo $HWASAN_OPTIONS
para ver as configurações atuais).
"bug aninhado no mesmo tópico"
Isso significa que houve um bug ao gerar o relatório de travamento do HWASan. Isso geralmente ocorre devido a um bug no tempo de execução do HWASan, registre um bug e forneça instruções sobre como reproduzir o problema, se possível.