Limpador HWAddress

O Android NDK tem suporte ao Limpador de endereços HW (link em inglês), também conhecido como HWASan, do NDK r21 e do Android 10 em diante (nível 29 da API). O HWASan só está disponível em dispositivos Arm de 64bits.

O HWASan é uma ferramenta de detecção de erros de memória semelhante ao ASan. Em comparação com o ASan clássico, o HWASan tem:

  • Sobrecarga de CPU semelhante (~2x)
  • Sobrecarga de tamanho de código semelhante (40 a 50%)
  • Sobrecarga de RAM muito menor (10% a 35%)

O HWASan detecta o mesmo conjunto de bugs do ASan:

  • Excesso ou falta do buffer de heap e pilha
  • Uso de heap depois da liberação
  • Uso de pilha fora do escopo
  • Double free ou wild free

Além disso, o HWASan também detecta:

  • Uso de pilha após retorno

App de exemplo

Um app de exemplo (link em inglês) mostra como configurar uma variante de build para o HWASan.

Criar

Para criar o código nativo (JNI) do seu app com o Limpador de endereços HW (link em inglês), faça o seguinte:

ndk-build

No seu arquivo Application.mk:

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

No arquivo build.gradle do seu módulo:

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 no CMakeLists.txt:

target_compile_options(${TARGET} PUBLIC -fsanitize=hwaddress -fno-omit-frame-pointer)
target_link_options(${TARGET} PUBLIC -fsanitize=hwaddress)

Com o NDK 27 ou mais recente, também é possível usar o seguinte em build.gradle e não precisar mudar o CMakeLists.txt:

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

Isso não vai funcionar ao usar ANDROID_USE_LEGACY_TOOLCHAIN_FILE=false.

Android 14 ou versão mais recente: adicionar o wrap.sh

Se você está executando o Android 14 ou mais recente, use um script wrap.sh para executar o app depurável em qualquer dispositivo Android. Pule esta etapa se você decidiu seguir as etapas nas Instruções de configuração.

Siga as instruções de empacotamento de um script wrap.sh para adicionar o seguinte script wrap.sh em arm64-v8a.

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

Executar

Se você estiver executando em uma versão do Android anterior à 14 ou não tiver adicionado um script wrap.sh, siga as instruções de configuração antes de executar o app.

Execute o app normalmente. Quando um erro de memória é detectado, um app falha com SIGABRT e mostra uma mensagem detalhada no Logcat. Uma cópia da mensagem pode ser encontrada em um arquivo em /data/tombstones e tem esta aparência:

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)

A mensagem pode ser seguida de outras informações de depuração, incluindo a lista de linhas de execução ativas no aplicativo, tags de alocação de memória próximas e valores de registro da CPU.

Consulte Noções básicas sobre os relatórios do HWASan para mais informações sobre as mensagens de erro dessa ferramenta.

Como criar executáveis de linha de comando

É possível criar e executar executáveis instrumentados com o HWASan no Android 14 e versões mais recentes. É possível usar a mesma configuração descrita em Build para ndk-build ou CMake para os executáveis. Envie os executáveis para um dispositivo com o Android 14 ou mais recente e execute-os normalmente usando o shell.

Se você estiver usando a libc++, verifique se está usando a STL compartilhada e envie-a para o dispositivo e defina LD_LIBRARY_PATH para o diretório que a contém ao executar o binário.

Se você não estiver usando o Gradle, consulte a documentação do NDK para saber como criar na linha de comando com o CMake e o ndk-build.

Android 13 ou versões anteriores: configuração

Se o dispositivo tiver o Android 14 ou mais recente, pule esta etapa e siga as instruções para usar o wrap.sh na seção Criar. Você também pode seguir esta seção e pular as instruções para usar o wrap.sh.

Em versões anteriores ao Android 14, os aplicativos HWASan precisam de um build HWASan do Android para serem executados. Atualize as imagens HWASan pré-criadas para dispositivos Pixel com suporte. Os builds estão disponíveis em ci.android.com, onde você pode clicar no quadrado do build exato para gerar um link de build para atualização. É necessário que você saiba o codinome do seu smartphone.

Atualização de um build do dispositivo

Pode ser mais fácil acessar flash.android.com diretamente, porque o fluxo começa com a detecção do dispositivo e mostra apenas as versões que você pode usar. As imagens a seguir ilustram o fluxo de configuração nessa ferramenta.

Ative o modo de desenvolvedor no dispositivo e o conecte ao computador usando um cabo USB. Clique em Add new device, selecione seu dispositivo na caixa de diálogo e clique em Connect.

Detectar um dispositivo para atualizar Seleção do dispositivo para se conectar

Depois que o dispositivo estiver conectado, clique nele para configurar o build. Na caixa Select a build ID, selecione a ramificação aosp-master-with-phones-throttled para escolher automaticamente a imagem correta para o dispositivo conectado.

Selecione o dispositivo a ser atualizado Confirme as opções de atualização e atualize o dispositivo

Clique em Install para atualizar o dispositivo.

Veja mais detalhes sobre a configuração necessária na documentação do Android Flash Tool. Ou consulte a documentação do AOSP para ver instruções sobre como criar uma imagem HWASan a partir da origem.