Faire en sorte que le stream de contrôle d’impression des fonctions GDB soit appelé

Comment créer des fonctions d’intérêt gdb intéressantes comme on les appelle, en retrait en fonction de leur profondeur dans la stack?

Je veux pouvoir dire quelque chose comme (composé):

(gdb) trace Foo* Bar* printf 

Et demandez à gdb d’imprimer toutes les fonctions qui commencent par Foo ou Bar, comme on les appelle. Un peu comme gnu cflow, excepté l’utilisation des symboles de débogage et uniquement des fonctions d’impression qui sont effectivement appelées, mais pas tous les stream d’appel possibles.

Les outils qui ne vont pas aider incluent cachegrind, callgrind et oprofile, qui classent les résultats en fonction desquels les fonctions ont été appelées le plus souvent. J’ai besoin que l’ordre d’appel soit conservé.

Le wildcarding (ou équivalent) est essentiel, car il y a beaucoup de fonctions Foo et Bar. Bien que je me contenterais d’enregistrer absolument chaque fonction. Ou peut-être dire à gdb d’enregistrer toutes les fonctions d’une bibliothèque particulière.

Certains assistants GDB doivent avoir un script pour ce travail courant!

Dans votre cas, je voudrais passer à la commande define de gdb, qui vous permet de définir une fonction pouvant prendre jusqu’à 10 arguments.

Vous pouvez transmettre les noms des fonctions à “tracer” en tant qu’arguments de la fonction que vous définissez ou les enregistrer tous dans la fonction elle-même. Je ferais quelque chose comme ce qui suit

 define functiontrace if $arg0 break $arg0 commands where continue end end if $arg1 ... 

Les arguments d’une fonction définie par l’utilisateur dans gdb sont référencés sous la forme $ arg0- $ arg9. Sinon, vous pouvez simplement enregistrer chaque fonction que vous souhaitez tracer au lieu d’utiliser $ arg0-9.

Remarque: ceci n’induira pas la profondeur dans la trace de stack, mais imprimera la trace de stack à chaque appel de la fonction. Je trouve cette approche plus utile que strace, etc., car elle enregistrera toutes les fonctions de votre choix, système, bibliothèque, locale ou autre.

rbreak cmd accepte les expressions rationnelles pour définir des points d’arrêt. Vous pouvez utiliser:

 (gdb) rbreak Foo.* (gdb) rbreak Bar.* (gdb) break printf 

Voir ceci pour plus de détails sur les points d’arrêt.

Puis utilisez les commands pour imprimer chaque fonction comme elle s’appelle. Par exemple, laissez α = le numéro du dernier point d’arrêt (vous pouvez le vérifier si vous l’avez manqué) , puis faites:

 (gdb) commands 1-α Type commands for breakpoint(s) 1-α, one per line. End with a line saying just "end". >silent >bt 1 >c >end (gdb) 

Quelques explications: silent supprime les messages d’information inutiles, bt 1 imprime la dernière image de la trace (c’est-à-dire la fonction actuelle) , c est un raccourci pour continue , pour continuer l’exécution, et end n’est que le délimiteur de la liste de commandes.

NB : si vous tracez des fonctions de bibliothèque, vous voudrez peut-être attendre que lib soit chargé. Par exemple, définissez une pause dans main fonction main ou une fonction quelconque, exécutez l’application jusqu’à ce point, puis définissez uniquement les points d’arrêt souhaités.

Utilisez le bon outil pour le travail;)

Comment imprimer automatiquement les N prochaines lignes exécutées dans GDB?

Avez-vous vu l’excellente réponse de litb à un message similaire ici ?

Il utilise readelf pour obtenir des symboles intéressants, des commandes gdb pour obtenir la trace et awk pour coller tout cela.

En gros, vous devez changer son script de commande gdb pour supprimer la profondeur de 1 de la trace pour voir la stack et filtrer des fonctions spécifiques, et reformater la sortie avec un script awk / python / (…) afin de la présenter comme un fichier. arbre. (J’avoue que je suis trop paresseux pour le faire maintenant …)

Vous pouvez appeler gdb en mode de traitement par lots (avec l’option -x ), interrompre la egrep si nécessaire et demander une trace ( bt ), puis filtrer le résultat à l’aide de grep ou d’ egrep .

Les retraits sont plus difficiles, mais la sortie bt est ordonnée afin que vous ayez la fonction actuelle en haut de la trace et la fonction main en bas.

Donc, vous créez un fichier avec des commandes:

 br  run bt kill quit 

puis exécutez gdb -x

Filtrer les chaînes qui commencent par # – vous obtenez un suivi de stack.