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 no seu build.gradle
e não seja necessário alterar 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ê tiver decidido 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ê está usando uma versão do Android anterior à 14 ou não adicionou um wrap.sh siga as Instruções de configuração antes de executar seu aplicativo.
Execute o app normalmente. Quando um erro de memória é detectado, um aplicativo falha com
SIGABRT e mostra uma mensagem detalhada no logcat. Uma cópia da mensagem pode
em um arquivo abaixo de /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
Você pode criar e executar executáveis instrumentados com o HWASan no Android 14 e mais recentes. Você pode usar a mesma configuração descrita em Build para ndk-build ou CMake para executáveis. Enviar os executáveis para um dispositivo executando o Android 14 ou mais recente e executando normalmente usando o shell.
Se você usar a libc++, use a STL compartilhada e envie-a para
o dispositivo e defina LD_LIBRARY_PATH
como o diretório que o contém quando
ao executar o binário.
Se você não usa o Gradle, consulte a documentação do NDK para aprender a criar usando a linha de comando com CMake e 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 abaixo. Você também pode seguir esta seção e pular as instruções para usar o wrap.sh abaixo.
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.
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.
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.
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.