Questo documento mostra come attivare strumenti di debug speciali quando si utilizza AGDE. Questi strumenti possono essere utili per la diagnosi di errori di sovrascrittura e di danneggiamento della memoria difficili da diagnosticare.
HWAddress Sanitizer e Address Sanitizer
HWAddress Sanitizer (HWASan) e Address Sanitizer (ASan) sono strumenti di debug per il danneggiamento della memoria che aiutano a eseguire il debug del danneggiamento della memoria e degli errori di sovrascrittura, come i seguenti:
- Overflow e underflow del buffer dello stack
- Sovrabbondanza e sottostima del buffer dell'heap
- Utilizzo dello stack al di fuori del relativo ambito
- Errori double free e wild free
- Utilizzo dello stack dopo il ritorno (solo HWASan)
Ti consigliamo di attivare HWASan o ASan solo quando stai eseguendo il debug di un problema o nell'ambito dei test automatici. Sebbene questi strumenti siano efficaci, il loro utilizzo comporta una penalizzazione.
Comportamento di runtime
Se abilitati, sia HWASan che ASan controllano automaticamente la presenza di errori di corruzione della memoria nella tua app.
Se viene rilevato un errore di memoria, l'app si arresta in modo anomalo con un errore SIGBART
(interruzione del segnale) e stampa un messaggio dettagliato in logcat. Una copia del messaggio viene anche scritta in un file in /data/tombstones
.
Il messaggio di errore è simile al seguente:
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)
Prerequisiti
Requisiti di HWASan
Per utilizzare HWASan:
- Devi utilizzare AGDE 24.1.99 o versioni successive.
- L'app deve essere compilata utilizzando NDK 26 o versioni successive.
- L'app deve essere compilata con SDK target 34 o versioni successive.
- Il target deve essere un dispositivo
arm64-v8a
con Android 14 (livello API 34) o versioni successive.
Utilizzare la libreria standard C++ condivisa nel progetto
A causa di un problema noto, ASan non è compatibile con la gestione delle eccezioni C++ quando si utilizza libc++_static
. Questo problema non si verifica quando si utilizza libc++_shared
.
HWASan ha una propria implementazione degli operatori new
e delete
, che non possono essere utilizzati se la libreria standard è collegata in modo statico al progetto.
Per modificare questa impostazione, consulta la sezione Eseguire il collegamento della libreria standard C++ di questo documento.
Attivare la generazione di Frame Pointer
HWASan e ASan utilizzano un smontatore basato su puntatori frame rapidi per generare informazioni sulla traccia dello stack per gli eventi di allocazione e deallocazione della memoria. Ciò significa che per utilizzare queste funzionalità devi attivare la generazione di puntatori frame nelle impostazioni del compilatore C++. In altre parole, devi disattivare l'ottimizzazione dell'omissione dell'indicatore frame.
Per modificare questa impostazione, consulta la sezione Attivare la generazione di puntatori frame di questo documento.
Configurare il progetto Visual Studio per l'utilizzo di HWASan o ASan
Attivazione di HWASan o ASan
Per attivare HWASan o ASan, vai a Proprietà di configurazione > Generale nelle pagine Property del progetto.
Figura 1: l'opzione Proprietà del progetto nella finestra Esplora progetti di Visual Studio.
Figura 2: l'impostazione Address Sanitizer (ASan) nelle proprietà del progetto generale.
Per attivare HWASan per il tuo progetto, modifica l'impostazione Address Sanitizer (ASan) in Hardware ASan Enabled (fsanitize=hwaddress).
Per attivare ASan per il progetto, modifica l'impostazione Address Sanitizer (ASan) in ASan Enabled (fsanitize=address).
Attivazione della generazione di Frame Pointer
La generazione dell'indicatore frame è controllata dall'impostazione del compilatore C/C++ Ometti indicatore frame ed è disponibile nelle Pagine delle proprietà del progetto in Proprietà di configurazione > C/C++ > Ottimizzazione.
Figura 3: dove trovare l'impostazione Ometti puntatore frame.
Quando utilizzi HWASan o ASan, imposta l'impostazione Ometti puntatore frame su No (-fno-omit-frame-pointer).
Collegamento della libreria standard C++ in modalità di libreria condivisa
L'impostazione della modalità del linker per la libreria standard C++ si trova nelle Property Pages (Pagine delle proprietà) del progetto in Configuration Properties > General (Proprietà di configurazione > Generale), nella sezione Project Defaults (Valori predefiniti del progetto).
Figura 4: dove trovare l'impostazione della modalità del linker per la libreria standard C++.
Quando utilizzi HWASan o ASan, imposta Utilizzo di STL su Utilizza librerie standard C++ (.so). Questo valore collega la libreria standard C++ al progetto come libreria condivisa, che è necessaria per il corretto funzionamento di HWASan e ASan.
Creazione di una configurazione di compilazione per l'utilizzo di Address Sanitizer
Se preferisci utilizzare HWASan o ASan in modo temporaneo, potresti non voler creare una nuova configurazione di compilazione esclusivamente per il loro utilizzo. Questo potrebbe accadere se il progetto è di piccole dimensioni, se stai esplorando la funzionalità o in risposta a un problema rilevato durante il test.
Tuttavia, se lo ritieni utile e prevedi di utilizzarlo regolarmente, ti consigliamo di creare una nuova configurazione di compilazione per HWASan o ASan, come mostrato nell'esempio Teapot. Ad esempio, puoi farlo se esegui regolarmente Address Sanitizer nell'ambito dei test di unità o durante i test di verifica notturni del tuo gioco.
La creazione di una configurazione di build separata potrebbe essere particolarmente utile se hai un progetto di grandi dimensioni che utilizza un numero elevato di librerie di terze parti diverse, che in genere colleghi in modo statico alla libreria standard C++. Le configurazioni di compilazione dedicate possono contribuire ad assicurare che le impostazioni del progetto rimangano sempre accurate.
Per creare una configurazione di compilazione, fai clic sul pulsante Configuration Manager… (Gestione configurazione…) nelle Property Pages (Pagine delle proprietà) del progetto e poi apri il menu a discesa Active solution configuration (Configurazione soluzione attiva). Quindi seleziona
Utilizzo di HWASan con allocatori di memoria personalizzati
HWASan intercetta automaticamente la memoria allocata tramite malloc
(o new
)
in modo da poter iniettare i tag nei puntatori e verificare la presenza di mancate corrispondenze dei tag.
Tuttavia, quando utilizzi un allocatore di memoria personalizzato, HWASan non è in grado di intercettare automaticamente i tuoi metodi di allocazione della memoria personalizzata. Pertanto, se vuoi utilizzare HWASan con il tuo allocatore di memoria personalizzato, devi eseguire l'instrumentazione dell'allocatore di memoria in modo che chiami HWASan esplicitamente. Questa operazione può essere eseguita con poche righe di codice.
Prerequisiti
I metodi HWASan che devi chiamare sono definiti in questa intestazione:
#include "sanitizer/hwasan_interface.h"
Strumenta il metodo di allocazione della memoria
Alloca gli oggetti con granularità e allineamento dei blocchi di 16 byte. Ad esempio, se hai un allocatore di pool che gestisce oggetti di dimensioni fisse di 24 byte, arrotonda le allocazioni a 32 byte e allineale a 16 byte.
Genera un tag a 8 bit. Il tag non deve utilizzare i valori 0-16, poiché sono riservati per uso interno.
Attiva HWASan per iniziare a monitorare la regione di memoria con quel tag:
__hwasan_tag_memory((void*) address, tag, size);
Inserisci il tag negli 8 bit superiori del cursore:
address = __hwasan_tag_pointer((void*) address, tag);
Strumenta il metodo di deallocazione della memoria
Reimposta il tag per la regione di memoria in modo che gli accessi tramite i puntatori taggati esistenti non vadano a buon fine:
__hwasan_tag_memory(__hwasan_tag_pointer(ptr, 0), 0, size);
Utilizzo di un pool di oggetti preallocati
Se l'allocatore di memoria prealloca gli oggetti in un pool e li restituisce al pool anziché liberarli effettivamente, il metodo di deallocazione può sovrascrivere direttamente il tag per la memoria e il puntatore con un nuovo valore:
```
__hwasan_tag_memory(__hwasan_tag_pointer(ptr, 0), tag, size);
ptr = __hwasan_tag_pointer((void*)ptr, tag);
```
Se utilizzi questa tecnica, i metodi di allocazione non devono taggare i puntatori o i blocchi di memoria, ma devono taggare i puntatori e i blocchi di memoria quando preallochi gli oggetti nel pool. Consulta PoolAllocator sample per un esempio che utilizza questo stile.