Lors du débogage et du profilage d'applications avec du code natif, il est souvent utile d'utiliser des outils de débogage qui doivent être activés au démarrage du processus. Cela nécessite d'exécuter votre application dans un processus récent plutôt que de le cloner à partir du processus zygote. Exemples :
- Traçage des appels système avec strace
- Identification des bugs de mémoire avec le débogage malloc ou ASan (Address Sanitizer)
- Profilage avec Simpleperf
Utiliser le script shell d'encapsulation
L'utilisation de wrap.sh
est simple :
- Compilez un fichier APK débogable personnalisé qui regroupe les éléments suivants :
- Un script shell nommé
wrap.sh
(pour en savoir plus, consultez les sections Créer le script shell d'encapsulation et Package wrap.sh) - Tous les outils supplémentaires dont votre script shell a besoin (tels que votre propre binaire
strace
)
- Un script shell nommé
- Installez le fichier APK débogable sur un appareil.
- Lancez l'application.
Créer le script shell d'encapsulation
Lorsque vous lancez un fichier APK débogable contenant wrap.sh
, le système exécute le script et transmet la commande pour démarrer l'application en tant qu'arguments. Le script est chargé de démarrer l'application, mais peut apporter des modifications à l'environnement ou aux arguments. Le script doit suivre la syntaxe du shell MirBSD Korn (mksh).
L'extrait de code suivant montre comment écrire un fichier wrap.sh
simple qui démarre simplement l'application :
#!/system/bin/sh exec "$@"
Débogage malloc
Pour utiliser le débogage malloc via wrap.sh
, vous devez inclure la ligne suivante :
#!/system/bin/sh LIBC_DEBUG_MALLOC_OPTIONS=backtrace logwrapper "$@"
ASan
La documentation ASan fournit un exemple de procédure pour ASan.
Package wrap.sh
Pour bénéficier de wrap.sh
, le fichier APK doit être débogable. Assurez-vous que le paramètre android:debuggable="true"
est configuré dans l'élément <application>
du fichier manifeste Android, ou si vous utilisez Android Studio, que vous avez configuré une version de débogage dans le fichier build.gradle
.
Vous devez également définir useLegacyPackaging
sur true
dans le fichier build.gradle
de votre application. Dans la plupart des cas, cette option est définie sur false
par défaut. Vous pouvez donc définir cette option explicitement sur true
pour éviter toute surprise.
Vous devez empaqueter le script wrap.sh
avec les bibliothèques natives de l'application. Si votre application ne contient pas de bibliothèques natives, ajoutez le répertoire lib manuellement au répertoire de votre projet. Pour chaque architecture compatible avec votre application, vous devez fournir une copie du script shell d'encapsulation dans ce répertoire natif de la bibliothèque.
L'exemple suivant présente la mise en page du fichier compatible avec les architectures ARMv8 et x86-64 :
# App Directory |- AndroidManifest.xml |- … |- lib |- arm64-v8a |- ... |- wrap.sh |- x86_64 |- ... |- wrap.sh
Android Studio empaquette uniquement les fichiers .so
des répertoires lib/
. Dès lors, si vous utilisez Android Studio, vous devez placer les fichiers wrap.sh
dans les répertoires src/main/resources/lib/*
pour qu'ils soient correctement empaquetés.
Notez que resources/lib/x86
s'affiche dans l'interface utilisateur sous la forme lib.x86
, mais il s'agit en réalité d'un sous-répertoire :
Effectuer un débogage avec wrap.sh
Si vous souhaitez associer un débogueur lorsque vous utilisez wrap.sh
, votre script shell doit activer manuellement le débogage. Étant donné que les étapes varient en fonction des versions, cet exemple montre comment ajouter les options appropriées pour toutes les versions compatibles avec wrap.sh
:
#!/system/bin/sh
cmd=$1
shift
os_version=$(getprop ro.build.version.sdk)
if [ "$os_version" -eq "27" ]; then
cmd="$cmd -Xrunjdwp:transport=dt_android_adb,suspend=n,server=y -Xcompiler-option --debuggable $@"
elif [ "$os_version" -eq "28" ]; then
cmd="$cmd -XjdwpProvider:adbconnection -XjdwpOptions:suspend=n,server=y -Xcompiler-option --debuggable $@"
else
cmd="$cmd -XjdwpProvider:adbconnection -XjdwpOptions:suspend=n,server=y $@"
fi
exec $cmd