Analyser le plantage d'un programme
De Wiki de la communauté Mandriva.
Si vous voulez aider à sa traduction, cliquez simplement sur l'onglet modifier. Vous pouvez contacter le traducteur en cliquant sur son nom et en modifiant sa page de discussion.
Consultez également les autres pages à traduire.
Sommaire |
Préliminaires
Vous devriez installer le paquetage contenant -debug à la fin du nom et toutes les bibliothèques qui lui sont liées. Cela va permettre aux outils de débogage de trouver des informations utiles.
Pour trouver le nom du paquetage de débogage, voici une méthode automatique :
$ rpm -qf --qf "%{SOURCERPM}\n" /usr/lib/libz.so.1.2.3 | sed 's/-[^-]*-[^-]*$/-debug/'
zlib-debug
Si vous oubliez quelques bibliothèques, vous obtiendrez leur nom en effectuant une requçete de « backtrace » dans gdb. Vous pourrez ainsi installer paquetage debug et redémarrer gdb. Dans l'exemple suivant, il me manque le paquetage -debug pour /lib64/libc.so.6 :
(gdb) bt #0 0x00002b526953c7ef in poll () from /lib64/libc.so.6 #1 0x00002b52691f412e in g_main_context_iterate (context=0x51f2d0, block=1, dispatch=1, selfVariable "self" is not available. ) at gc:2977 #2 0x00002b52691f45ea in IA__g_main_loop_run (loop=0x53ad10) at gc:2879
Quand c'est fait, vous pouvez commencer à collecter des précieuses informations en utilisant les outils variés listés ci-dessous.
gdb
gdb est « GNU debugger » (le débogueur GNU). Il est disponible dans le paquetage gdb. Quand un programme crashe à cause d'une erreur de segmentation (segfault, ou segmentation fault) ou un avortage (« abort »), gdb va vous permettre d'avoir un « backetrace », qui contiendra les informations sur où l'erreur est survenue, et de quoi provenait-elle.
Faire tourner vos applications dans gdb
Si vous pouvez reproduire le crash facilement, alors vous pouvez lancer votre application depuis gdb et obtenir des informations utiles au moment de l'arrêt.
- Lancez gdb en lui donnant le chemin de votre application et ajoutez si besoin les paramètres.
[pterjan@coin ~]$ gdb /bin/cat GNU gdb 6.3-7mdv2007.0 (Mandriva Linux release 2007.0) Copyright 2004 Free Software Foundation, Inc. GDB is free software, covered by the GNU General Public License, and you are welcome to change it and/or distribute copies of it under certain conditions. Type "show copying" to see the conditions. There is absolutely no warranty for GDB. Type "show warranty" for details. This GDB was configured as "x86_64-mandriva-linux-gnu"...(no debugging symbols found) Using host libthread_db library "/lib64/libthread_db.so.1". (gdb) run /proc Starting program: /bin/cat /proc /bin/cat: /proc: Is a directory Program exited with code 01. (gdb)
- Si vous obtenez des messages concernant le signal 33, vous devez demander à gdb de ne pas s'arrêter et de transmettre le signal à l'application. Donc vous le relancez ainsi:
Program received signal SIG33, Real-time event 33. [Switching to Thread 1182845264 (LWP 11543)] 0x00002b661d87d536 in pthread_cond_wait@@GLIBC_2.3.2 () from /lib/libpthread.so.0 (gdb) handle SIG33 nostop noprint noignore pass Signal Stop Print Pass to program Description SIG33 No No Yes Real-time event 33 (gdb) kill Kill the program being debugged? (y or n) y (gdb) run
- Lorsque le programme se bloque, vous avez une invite gdb. Vous affichez le "backtrace" avec la commande bt full, ce sont les informations nécessaires pour le rapport de bogue. Si les messages précédents parlent de "threads", vous pouvez obtenir tous les "backtraces" avec thread apply all bt full.
(gdb) bt full
#0 0x00002b526953c7ef in poll () from /lib64/libc.so.6
No symbol table info available.
#1 0x00002b52691f412e in g_main_context_iterate (context=0x51f2d0, block=1, dispatch=1, self=Variable "self" is not available.
) at gc:2977
max_priority = 2147483647
timeout = 30000
some_ready = Variable "some_ready" is not available.
Exécuter gdb sur un fichier "core"
Si, pour quelque raison vous ne pouvez pas reproduire facilement le crash à l'intérieur de gdb mais que vous obtenez un fichier core, vous pouvez faire une analyse post-mortem. Donnez seulement à gdb votre application et le fichier "core" comme gdb / bin / cat core.42, puis demandez un backtrace avec thread apply all bt full. Si aucun "core" n'est généré après une erreur de segmentation, essayez d'exécuter ulimit-c unlimited dans le shell depuis lequel vous allez lancer votre application.
Utiliser gdb avec une application en cours
Le débogage des applications au démarrage complexe, par exemple les services système, peut être délicat car gdb n'exécute pas de script et que vous ne pouvez pas connaître l'ensemble des paramètres que le script finit par utiliser quand il lance l'exécutable binaire.
Dans de tels cas (si le crash ne se produit pas pendant le démarrage), vous pouvez attacher gdb à une instance de l'application en cours.
Tout d'abord, identifier le processus dans lequel le crash va se produire, par exemple avecps ax | grep nom_appli
Si l'application lance des processus multiples, essayez de noter tous ceux mis en cause dans le crash, et vérifiez syslog pour voir lequel d'entre eux à provoqué réellement le plantage; lorsque vous redémarrez l'application, vous pouvez attacher gdb au processus qui occupe la même place relative dans la liste.
Ensuite, attachez gdb au processus en utilisant gdb nom_de_l'exécutable id_du_processus. Ainsi gdb sera attaché à ce processus et le suspendra. Pour reprendre son exécution, utilisez la commande gdb: c.
Enfin, provoquez le crash. gdb vous informera, affichera une invite et vous pourrez demander une trace.
Si vous devez lancer gdb depuis un terminal, ajoutez > fichierdesortie 2> & 1 à la commande gdb, ce qui va rediriger toutes les sorties vers ce fichier. Bien sûr, cela signifie que vous ne verrez rien sur le tty où gdb tourne. Donc dans un autre terminal, lancez tail -f fichierdesortie, ce qui vous permettra de voir ce qui se passe. Ayez cependant à l'esprit que toute entrée que vous voulez donner à gdb doit être tapée sur le terminal où gdb tourne, et non sur le terminal où tail est lancé (et où elle sera ignorée). Lorsque vous aurez terminé, le fichierdesortie contiendra votre session gdb.
Strace
strace liste tous les appels système effectués par l'application (ouvrir un fichier, lire sur un socket réseau, ...) et qui peuvent aider à résoudre certaines questions, comme un fichier manquant, un répertoire non accessible en écriture, ...
Vous pouvez l'exécuter avec strace -f -o outputfile command. Par exemple strace -f -o ls.strace ls /tmp lancera ls /tmp et écrira la liste tous les appels système dans le ficher ls.strace.
ltrace
valgrind
Quand un programme est exécuté sous la supervision de Valgrind, toutes les lectures et écritures en mémoire sont vérifiées, et les appels à malloc / new / free / delete sont interceptés. En conséquence, Valgrind peut détecter des problèmes tels que:
- Utilisation de mémoire non initialisée
- Lecture / écriture de la mémoire après qu'elle a été libérée
- Lecture / écriture de la fin des blocs alloués par malloc
- Lecture / écriture de zones inappropriées sur la pile
- Fuites de mémoire -- où des pointeurs vers les blocs alloués par malloc sont perdus à jamais
- Passage à des appels système de blocs mémoire non initialisée et/ou non adressable
- Utilisation incohérente des paires malloc/free, new/delete ...

