Ce document explique comment activer des outils de débogage spéciaux lorsque vous utilisez AGDE. Ces outils contribuent à diagnostiquer les corruptions de mémoire et à écraser les erreurs.
HWAddress Sanitizer et Address Sanitizer
HWAddress Sanitizer (HWASan) et Address Sanitizer (ASan) sont des outils de débogage des corruptions de mémoire. Ils permettent de déboguer ce type de problème et d'écraser les erreurs telles que les suivantes :
- Débordement positif ou négatif de la mémoire tampon allouée par la pile
- Débordement positif ou négatif du tampon de tas de mémoire
- Utilisation de la pile en dehors de son champ d'application
- Erreurs d'appels multiples ou aléatoires de "free"
- Utilisation de la pile après le retour (HWASan uniquement)
Nous vous recommandons de n'activer HWASan ou ASan que lorsque vous déboguez un problème ou dans le cadre de tests automatisés. Même si ces outils sont performants, leur utilisation peut donner lieu à une pénalité.
Comportement lors de l'exécution
Lorsqu'ils sont activés, HWASan et ASan vérifient automatiquement qu'il n'y a pas de corruption de mémoire dans votre application.
Si un problème de mémoire est détecté, l'application plante avec l'erreur SIGBART
(abandon du signal) et affiche un message détaillé dans logcat. Une copie de ce message est également écrite dans un fichier sous /data/tombstones
.
Le message d'erreur ressemble à ceci :
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)
Prérequis
Exigences concernant HWASan
Pour utiliser HWASan:
- Vous devez utiliser AGDE 24.1.99 ou une version ultérieure.
- L'application doit être compilée à l'aide du NDK 26 ou version ultérieure.
- L'application doit être compilée avec le SDK cible 34 ou une version ultérieure.
- La cible doit être un appareil
arm64-v8a
équipé d'Android 14 (niveau d'API 34) ou version ultérieure.
Utiliser la bibliothèque standard C++ partagée dans votre projet
En raison d'un problème connu, ASan n'est pas compatible avec la gestion des exceptions C++ lorsque vous utilisez libc++_static
. Ce problème ne survient pas lorsque vous utilisez libc++_shared
.
HWASan dispose de sa propre implémentation des opérateurs new
et delete
, qui ne peuvent pas être utilisés si la bibliothèque standard est associée de manière statique au projet.
Pour modifier ce paramètre, consultez la section Associer la bibliothèque standard C++ de ce document.
Activer la génération du pointeur de frame
HWASan et ASan utilisent un dérouleur "rapide" basé sur un pointeur de frame pour générer des informations de trace de la pile pour les événements d'allocation et de désallocation de mémoire. Par conséquent, vous devez activer la génération du pointeur de frame dans les paramètres de compilation C++ pour pouvoir utiliser ces fonctionnalités. Autrement dit, vous devez désactiver l'optimisation de l'omission du pointeur de frame.
Pour modifier ce paramètre, consultez la section Comment activer la génération du pointeur de frame de ce document.
Configurer votre projet Visual Studio pour utiliser HWASan ou ASan
Activer HWASan ou ASan
Pour activer HWASan ou ASan, accédez à Configuration Properties > General (Propriétés de la configuration > Général) dans les pages de propriétés du projet.
Figure 1 : Option Properties (Propriétés) du projet dans la fenêtre de l'Explorateur de solutions de Visual Studio
Figure 2 : Paramètre Address Sanitizer (ASan) dans les propriétés générales du projet
Pour activer HWASan pour votre projet, définissez le paramètre Address Sanitizer (ASan) sur Hardware ASan Enabled (fsanitize=hwaddress) (Matériel ASan activé (fsanitize=hwaddress)).
Pour activer ASan pour votre projet, définissez le paramètre Address Sanitizer (ASan) sur ASan Enabled (fsanitize=address) (ASan activé (fsanitize=address)).
Comment activer la génération du pointeur de frame
La génération du pointeur de frame est contrôlée par le paramètre du compilateur C/C++ Omit Frame Pointer (Omettre le pointeur de frame). Elle se trouve dans la section Property Pages (Pages de propriétés) de votre projet, sous Configuration Properties > C/C++ > Optimization (Propriétés de configuration > C/C++ > Optimisation).
Figure 3 : Emplacement du paramètre Omit Frame Pointer (Omettre le pointeur de frame)
Lorsque vous utilisez HWASan ou ASan, définissez le paramètre Omit Frame Pointer (Omettre le pointeur de frame) sur No (-fno-omit-frame-pointer) (Non (-fno-omit-frame-pointer)).
Associer la bibliothèque standard C++ en mode bibliothèque partagée
Le paramètre du mode d'association de la bibliothèque standard C++ est disponible dans la section Property Pages (Pages de propriétés) de votre projet, sous Configuration Properties > General (Propriétés de la configuration > Général), dans les paramètres par défaut du projet.
Figure 4 : Emplacement du paramètre du mode d'association pour la bibliothèque standard C++
Lorsque vous utilisez HWASan ou ASan, définissez Use of STL (Utilisation de STL) sur Use C++ Standard Libraries (.so) (Utiliser des bibliothèques standards C++ (.so)). Cette valeur associe la bibliothèque standard C++ à votre projet en tant que bibliothèque partagée, ce qui est nécessaire au bon fonctionnement de HWASan et d'ASan.
Créer une configuration de compilation pour utiliser Address Sanitizer
Si vous préférez utiliser HWASan ou ASan de manière temporaire, vous pouvez choisir de ne pas créer de configuration de compilation réservée à leur utilisation. Cela peut être le cas si votre projet est de petite envergure, si vous souhaitez juste explorer cette fonctionnalité ou si vous avez à traiter un problème détecté lors des tests.
Toutefois, si vous jugez que cela peut être utile et si vous prévoyez de vous en servir régulièrement, vous pouvez créer une configuration de compilation pour HWASan ou ASan, comme indiqué dans l'exemple Teapot. Cette approche est, par exemple, conseillée si vous exécutez régulièrement Address Sanitizer lors de vos tests unitaires ou pendant les tests de détection de fumée de votre jeu.
La création d'une configuration de compilation distincte peut s'avérer particulièrement utile si vous disposez d'un projet volumineux avec un grand nombre de bibliothèques tierces différentes, que vous associez habituellement de manière statique à la bibliothèque standard C++. Les configurations de compilation dédiées permettent de garantir que les paramètres de votre projet restent exacts à tout moment.
Pour créer une configuration de compilation, dans la section Property Pages (Pages de propriétés) de votre projet, cliquez sur le bouton Configuration Manager (Gestionnaire de configuration), puis ouvrez le menu déroulant Active solution configuration (Active solution configuration). Sélectionnez ensuite
Utiliser HWASan avec des alloueurs de mémoire personnalisés
HWASan intercepte automatiquement la mémoire allouée via malloc
(ou new
) afin de pouvoir injecter des balises dans les pointeurs et vérifier les différences de balise.
Toutefois, lorsque vous utilisez un outil d'allocation de mémoire personnalisé, HWASan ne peut pas intercepter automatiquement vos méthodes d'allocation de mémoire personnalisées. Par conséquent, si vous souhaitez utiliser HWASan avec votre outil d'allocation de mémoire personnalisé, instrumentez-le pour qu'il appelle HWASan explicitement. Cela peut être fait en quelques lignes de code.
Prérequis
Les méthodes HWASan que vous devez appeler sont définies dans cet en-tête:
#include "sanitizer/hwasan_interface.h"
Instrumenter votre méthode d'allocation de mémoire
Allouer des objets avec une granularité et un alignement de bloc de 16 octets Par exemple, si vous disposez d'un alloueur de pool qui sert des objets de taille fixe de 24 octets, arrondissez vos allocations à 32 octets et alignez-les sur 16 octets.
Générez une balise 8 bits. Votre balise ne doit pas utiliser les valeurs 0 à 16, car elles sont réservées à un usage interne.
Activez HWASan pour commencer à suivre la région de mémoire avec ce tag:
__hwasan_tag_memory((void*) address, tag, size);
Injectez la balise dans les huit premiers bits de votre pointeur:
address = __hwasan_tag_pointer((void*) address, tag);
Instrumenter votre méthode de désallocation de mémoire
Réinitialisez la balise de la région de mémoire pour que les accès supplémentaires via les pointeurs tagués existants échouent:
__hwasan_tag_memory(__hwasan_tag_pointer(ptr, 0), 0, size);
Utiliser un pool d'objets préalloué
Si votre alloueur de mémoire préalloue des objets dans un pool et les renvoie dans le pool au lieu de les libérer, votre méthode de désallocation peut directement écraser la balise de la mémoire et le pointeur avec une nouvelle valeur:
```
__hwasan_tag_memory(__hwasan_tag_pointer(ptr, 0), tag, size);
ptr = __hwasan_tag_pointer((void*)ptr, tag);
```
Si vous utilisez cette technique, vos méthodes d'allocation n'ont pas besoin d'ajouter des balises aux pointeurs ni aux blocs de mémoire, mais elles doivent le faire lorsque vous préallouez les objets dans votre pool. Pour obtenir un exemple utilisant ce style, consultez l'exemple PoolAllocator.