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.
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.