3.4. Débogage d'une application bloquée
Parfois, il n'est pas possible de déboguer une application directement. Dans ce cas, vous pouvez collecter des informations sur l'application au moment de son arrêt et les analyser par la suite.
3.4.1. Core dumps : ce qu'ils sont et comment les utiliser
Un core dump est une copie d'une partie de la mémoire de l'application au moment où l'application a cessé de fonctionner, stockée au format ELF. Il contient toutes les variables internes et la pile de l'application, ce qui permet d'inspecter l'état final de l'application. Lorsqu'il est complété par le fichier exécutable correspondant et les informations de débogage, il est possible d'analyser un fichier core dump avec un débogueur d'une manière similaire à l'analyse d'un programme en cours d'exécution.
Le noyau du système d'exploitation Linux peut enregistrer des core dumps automatiquement, si cette fonctionnalité est activée. Vous pouvez également envoyer un signal à toute application en cours d'exécution pour qu'elle génère un core dump, quel que soit son état actuel.
Certaines limites peuvent affecter la capacité à générer un core dump. Pour connaître les limites actuelles :
$ ulimit -a
3.4.2. Enregistrement des plantages d'application avec les core dumps
Pour enregistrer les pannes d'application, configurez l'enregistrement de la vidange du noyau et ajoutez des informations sur le système.
Procédure
Pour activer les vidages de noyau, assurez-vous que le fichier
/etc/systemd/system.conf
contient les lignes suivantes :DumpCore=yes DefaultLimitCORE=infinity
Vous pouvez également ajouter des commentaires décrivant si ces paramètres étaient présents auparavant, et quelles étaient les valeurs précédentes. Cela vous permettra d'annuler ces modifications ultérieurement, si nécessaire. Les commentaires sont des lignes commençant par le caractère
#
.La modification du fichier nécessite un accès de niveau administrateur.
Appliquer la nouvelle configuration :
# systemctl daemon-reexec
Supprimer les limites de taille du core dump :
# ulimit -c unlimited
Pour inverser ce changement, exécutez la commande avec la valeur
0
au lieu deunlimited
.Installez le paquet
sos
qui fournit l'utilitairesosreport
pour collecter des informations sur le système :# dnf install sos
-
Lorsqu'une application se bloque, un core dump est généré et traité par
systemd-coredump
. Créer un rapport SOS pour fournir des informations supplémentaires sur le système :
# sosreport
Cette opération crée une archive
.tar
contenant des informations sur votre système, telles que des copies des fichiers de configuration.Localiser et exporter le core dump :
$ coredumpctl list executable-name $ coredumpctl dump executable-name > /path/to/file-for-export
Si l'application s'est écrasée plusieurs fois, la sortie de la première commande énumère davantage de vidages de noyau capturés. Dans ce cas, construisez pour la deuxième commande une requête plus précise en utilisant les autres informations. Voir la page de manuel coredumpctl(1) pour plus de détails.
Transférez le core dump et le rapport SOS sur l'ordinateur où le débogage aura lieu. Transférez également le fichier exécutable, s'il est connu.
ImportantLorsque le fichier exécutable n'est pas connu, l'analyse ultérieure du fichier central permet de l'identifier.
- Facultatif : Supprimez le core dump et le rapport SOS après les avoir transférés, afin de libérer de l'espace disque.
Ressources supplémentaires
- Introduction à systemd dans le document Configuring basic system settings
- Comment activer les vidages de fichiers centraux lorsqu'une application se bloque ou qu'il y a des erreurs de segmentation - un article de la base de connaissances
- Qu'est-ce qu'un sosreport et comment en créer un dans Red Hat Enterprise Linux 4.6 et versions ultérieures ? - un article de la base de connaissances
3.4.3. Inspecter les états d'arrêt d'une application à l'aide de core dumps
Conditions préalables
- Vous devez disposer d'un fichier core dump et d'un rapport sos du système où la panne s'est produite.
- GDB et elfutils doivent être installés sur votre système.
Procédure
Pour identifier le fichier exécutable où le crash s'est produit, exécutez la commande
eu-unstrip
avec le fichier core dump :$ eu-unstrip -n --core=./core.9814 0x400000+0x207000 2818b2009547f780a5639c904cded443e564973e@0x400284 /usr/bin/sleep /usr/lib/debug/bin/sleep.debug [exe] 0x7fff26fff000+0x1000 1e2a683b7d877576970e4275d41a6aaec280795e@0x7fff26fff340 . - linux-vdso.so.1 0x35e7e00000+0x3b6000 374add1ead31ccb449779bc7ee7877de3377e5ad@0x35e7e00280 /usr/lib64/libc-2.14.90.so /usr/lib/debug/lib64/libc-2.14.90.so.debug libc.so.6 0x35e7a00000+0x224000 3ed9e61c2b7e707ce244816335776afa2ad0307d@0x35e7a001d8 /usr/lib64/ld-2.14.90.so /usr/lib/debug/lib64/ld-2.14.90.so.debug ld-linux-x86-64.so.2
La sortie contient les détails de chaque module sur une ligne, séparés par des espaces. Les informations sont listées dans cet ordre :
- L'adresse mémoire où le module a été mappé
- L'identifiant de construction du module et l'endroit où il a été trouvé dans la mémoire
-
Le nom du fichier exécutable du module, affiché sous la forme
-
s'il est inconnu, ou sous la forme.
si le module n'a pas été chargé à partir d'un fichier -
La source des informations de débogage, affichée sous la forme d'un nom de fichier lorsqu'elle est disponible, sous la forme de
.
lorsqu'elle est contenue dans le fichier exécutable lui-même, ou sous la forme de-
lorsqu'elle n'est pas présente du tout -
Le nom de la bibliothèque partagée (soname) ou
[exe]
pour le module principal
Dans cet exemple, les détails importants sont le nom du fichier
/usr/bin/sleep
et le build-id2818b2009547f780a5639c904cded443e564973e
sur la ligne contenant le texte[exe]
. Grâce à ces informations, vous pouvez identifier le fichier exécutable nécessaire à l'analyse du core dump.Obtenir le fichier exécutable qui s'est écrasé.
- Si possible, copiez-le à partir du système où la panne s'est produite. Utilisez le nom du fichier extrait du fichier principal.
Vous pouvez également utiliser un fichier exécutable identique sur votre système. Chaque fichier exécutable construit sur Red Hat Enterprise Linux contient une note avec une valeur build-id unique. Déterminez le build-id des fichiers exécutables pertinents disponibles localement :
$ eu-readelf -n executable_file
Utilisez ces informations pour faire correspondre le fichier exécutable du système distant avec votre copie locale. Le build-id du fichier local et le build-id listé dans le core dump doivent correspondre.
-
Enfin, si l'application est installée à partir d'un paquetage RPM, vous pouvez obtenir le fichier exécutable à partir du paquetage. Utilisez la sortie de
sosreport
pour trouver la version exacte du paquetage requis.
- Obtenez les bibliothèques partagées utilisées par le fichier exécutable. Utilisez les mêmes étapes que pour le fichier exécutable.
- Si l'application est distribuée sous forme de paquetage, chargez le fichier exécutable dans GDB, afin d'afficher des indications sur les paquets debuginfo manquants. Pour plus de détails, voir Section 3.1.4, « Obtenir les paquets d'informations de débogage pour une application ou une bibliothèque à l'aide de GDB ».
Pour examiner le fichier core en détail, chargez le fichier exécutable et le fichier core dump avec GDB :
$ gdb -e executable_file -c core_file
D'autres messages concernant les fichiers manquants et les informations de débogage vous aident à identifier ce qui manque pour la session de débogage. Revenez à l'étape précédente si nécessaire.
Si les informations de débogage de l'application sont disponibles sous la forme d'un fichier et non d'un paquet, chargez ce fichier dans GDB à l'aide de la commande
symbol-file
:(gdb) fichier-symbole program.debug
Remplacez program.debug par le nom réel du fichier.
NoteIl n'est peut-être pas nécessaire d'installer les informations de débogage pour tous les fichiers exécutables contenus dans le core dump. La plupart de ces fichiers exécutables sont des bibliothèques utilisées par le code de l'application. Ces bibliothèques peuvent ne pas contribuer directement au problème que vous analysez et vous n'avez pas besoin d'inclure les informations de débogage les concernant.
Utilisez les commandes GDB pour inspecter l'état de l'application au moment où elle s'est arrêtée. Voir Inspection de l'état interne de l'application avec GDB.
NoteLors de l'analyse d'un fichier core, GDB n'est pas attaché à un processus en cours d'exécution. Les commandes de contrôle de l'exécution n'ont aucun effet.
Ressources supplémentaires
- Débogage avec GDB - 2.1.1 Choix des fichiers
- Débogage avec GDB - 18.1 Commandes pour spécifier des fichiers
- Débogage avec GDB - 18.3 Informations de débogage dans des fichiers séparés
3.4.4. Créer et accéder à un core dump avec coredumpctl
L'outil coredumpctl
de systemd
peut considérablement rationaliser le travail avec les core dumps sur la machine où le crash s'est produit. Cette procédure explique comment capturer un core dump d'un processus qui ne répond pas.
Conditions préalables
Le système doit être configuré pour utiliser
systemd-coredump
pour la gestion du core dump. Pour vérifier que c'est bien le cas :$ sysctl kernel.core_pattern
La configuration est correcte si la sortie commence par ce qui suit :
kernel.core_pattern = |/usr/lib/systemd/systemd-coredump
Procédure
Trouver le PID du processus suspendu, sur la base d'une partie connue du nom du fichier exécutable :
$ pgrep -a executable-name-fragment
Cette commande produira une ligne sous la forme
PID command-line
Utilisez la valeur command-line pour vérifier que le site PID appartient au processus prévu.
Par exemple :
$ pgrep -a bc 5459 bc
Envoyer un signal d'abandon au processus :
# kill -ABRT PID
Vérifiez que le noyau a été capturé par
coredumpctl
:$ coredumpctl list PID
Par exemple :
$ coredumpctl list 5459 TIME PID UID GID SIG COREFILE EXE Thu 2019-11-07 15:14:46 CET 5459 1000 1000 6 present /usr/bin/bc
Examiner plus avant ou utiliser le fichier de base selon les besoins.
Vous pouvez spécifier le core dump par PID et d'autres valeurs. Voir la page de manuel coredumpctl(1) pour plus de détails.
Pour afficher les détails du fichier principal :
$ coredumpctl info PID
Pour charger le fichier core dans le débogueur GDB :
$ coredumpctl debug PID
En fonction de la disponibilité des informations de débogage, GDB suggérera des commandes à exécuter, telles que :
Missing separate debuginfos, use: dnf debuginfo-install bc-1.07.1-5.el8.x86_64
Pour plus de détails sur ce processus, voir Obtenir des paquets d'informations de débogage pour une application ou une bibliothèque à l'aide de GDB.
Pour exporter le fichier de base en vue d'un traitement ultérieur ailleurs :
$ coredumpctl dump PID > /path/to/file_for_export
Remplacez /path/to/file_for_export par le fichier dans lequel vous souhaitez placer le core dump.
3.4.5. Vider la mémoire du processus avec gcore
Le processus de débogage par vidage du noyau permet d'analyser l'état du programme hors ligne. Dans certains cas, vous pouvez utiliser ce processus avec un programme toujours en cours d'exécution, par exemple lorsqu'il est difficile d'accéder à l'environnement avec le processus. Vous pouvez utiliser la commande gcore
pour vidanger la mémoire de n'importe quel processus en cours d'exécution.
Conditions préalables
- Vous devez comprendre ce que sont les core dumps et comment ils sont créés.
- GDB doit être installé sur le système.
Procédure
Trouvez l'identifiant du processus (pid). Utilisez des outils tels que
ps
,pgrep
, ettop
:$ ps -C some-program
Vider la mémoire de ce processus :
$ gcore -o filename pid
Cette opération crée un fichier filename et y déverse la mémoire du processus. Pendant que la mémoire est vidée, l'exécution du processus est interrompue.
- Une fois le vidage du noyau terminé, le processus reprend son cours normal.
Créer un rapport SOS pour fournir des informations supplémentaires sur le système :
# sosreport
Cette opération crée une archive tar contenant des informations sur votre système, telles que des copies des fichiers de configuration.
- Transférez le fichier exécutable du programme, le core dump et le rapport SOS sur l'ordinateur où le débogage aura lieu.
- Facultatif : Supprimez le core dump et le rapport SOS après les avoir transférés, afin de libérer de l'espace disque.
Ressources supplémentaires
- Comment obtenir un fichier core sans redémarrer une application ? - Article de la base de connaissances
3.4.6. Vider la mémoire d'un processus protégé avec GDB
Vous pouvez marquer la mémoire des processus comme ne devant pas être vidée. Cela permet d'économiser des ressources et d'assurer une sécurité supplémentaire lorsque la mémoire du processus contient des données sensibles : par exemple, dans les applications bancaires ou comptables ou sur des machines virtuelles entières. Les vidanges du noyau (kdump
) et les vidanges manuelles du noyau (gcore
, GDB) ne vidangent pas la mémoire marquée de cette manière.
Dans certains cas, vous devez extraire tout le contenu de la mémoire du processus sans tenir compte de ces protections. Cette procédure montre comment procéder à l'aide du débogueur GDB.
Conditions préalables
- Vous devez comprendre ce que sont les core dumps.
- GDB doit être installé sur le système.
- GDB doit déjà être attaché au processus avec la mémoire protégée.
Procédure
Configurer GDB pour qu'il ignore les paramètres du fichier
/proc/PID/coredump_filter
:(gdb) set use-coredump-filter off
Configure GDB pour qu'il ignore le drapeau de page mémoire
VM_DONTDUMP
:(gdb) set dump-excluded-mappings on
Vider la mémoire :
(gdb) gcore core-file
Remplacez core-file par le nom du fichier dans lequel vous voulez vider la mémoire.
Ressources supplémentaires
- Débogage avec GDB - Comment produire un fichier Core à partir de votre programme