Obtenir GDB pour enregistrer une liste de points d'arrêt

129

OK, info break répertorie les points d'arrêt, mais pas dans un format qui fonctionnerait bien avec leur réutilisation en utilisant la commande - comme dans cette question . GDB a-t-il une méthode pour les transférer dans un fichier acceptable pour une nouvelle saisie? Parfois, dans une session de débogage, il est nécessaire de redémarrer GDB après avoir créé un ensemble de points d'arrêt pour les tests.

Le fichier .gdbinit a le même problème que --command. La commande info break ne répertorie pas les commandes, mais plutôt un tableau destiné à la consommation humaine.

Pour élaborer, voici un exemple de pause info :

(gdb) pause info
Num Type Disp Enb Address Quoi
1 point d'arrêt garder y 0x08048517 <foo :: bar (void) +7>
codeur occasionnel
la source

Réponses:

204

Depuis GDB 7.2 (23/08/2011), vous pouvez désormais utiliser la commande save breakpoints .

save breakpoints <filename>
  Save all current breakpoint definitions to a file suitable for use
  in a later debugging session.  To read the saved breakpoint
  definitions, use the `source' command.

Utilisez source <filename>pour restaurer les points d'arrêt enregistrés à partir du fichier.

aculich
la source
2
qu'en est-il s'ils proviennent d'une charge lib partagée? Il répond N par défaut il semble ...Make breakpoint pending on future shared library load? (y or [n]) [answered N; input not from terminal]
bjackfly
Notez que lorsque vous avez une condition de point d'arrêt qui ne peut pas être résolue au démarrage ( break g_log if log_level==G_LOG_LEVEL_CRITICAL), au moins gdb 7.8.1 arrêtera d'analyser d'autres commandes. Si vous avez des commandes supplémentaires qui doivent être exécutées pour ce point d'arrêt, placez la commandsligne avant la conditionligne.
Lekensteyn
@Andry J'ai rétrogradé votre modification à mon blockquote d'origine car le texte est une citation textuelle de la documentation ... Je serais autrement d'accord avec votre modification si c'était mes propres mots à la place.
aculich
@aculich: Je vois. Je recommanderais dans tous les cas d'utiliser le style de citation plutôt que le style de code.
Andry
26

Cette réponse est dépassée. GDB prend désormais en charge l'enregistrement direct. Voyez cette réponse .

Vous pouvez utiliser la journalisation:

(gdb) b main
Breakpoint 1 at 0x8049329
(gdb) info break
Num     Type           Disp Enb Address    What
1       breakpoint     keep y   0x08049329 <main+16>
(gdb) set logging file breaks.txt
(gdb) set logging on
Copying output to breaks.txt.
(gdb) info break
Num     Type           Disp Enb Address    What
1       breakpoint     keep y   0x08049329 <main+16>
(gdb) q

Le fichier breaks.txt contient maintenant:

Num     Type           Disp Enb Address    What
1       breakpoint     keep y   0x08049329 <main+16>

Il est facile d' écrire un script AWK qui le transforme en un format utile pour le .gdbinitou un --commandfichier. Ou vous pouvez même faire émettre le script séparément--eval-command de la ligne de commande GDB ...

L'ajout de cette petite macro à .gdbinit vous aidera à le faire:

# Call with dump_breaks file.txt
define dump_breaks
    set logging file $arg0
    set logging redirect on
    set logging on
    info breakpoints
    set logging off
    set logging redirect off
end
Johannes Schaub - litb
la source
On pourrait tout aussi bien utiliser le copier-coller, mais la méthode de script semble être la voie à suivre.
casualcoder
1
Je ne pense pas que le copier-coller soit plus facile que d'écrire un script une fois, puis de l'utiliser à nouveau :) après tout, c'est la raison même pour laquelle vous avez posé cette question en premier lieu, je pense :)
Johannes Schaub - litb
Euh, je voulais dire utiliser le copier-coller au lieu de la méthode de journalisation. Le script est-il si loin pour sûr.
casualcoder
Hou la la! gdb échoue! Je l'utilise tous les jours et j'aime beaucoup de ses fonctionnalités. Mais le manque est tout simplement stupide.
deft_code
4
Cette réponse a maintenant plus de 2 ans, elle peut donc être obsolète si vous utilisez une version plus récente de gdb. Depuis gdb 7.2, vous pouvez désormais utiliser la save breakpointscommande.
aculich
11

Placez vos commandes et points d'arrêt GDB dans un fichier .gdbinit comme vous pourriez les saisir à l' gdb>invite, et GDB les chargera et les exécutera automatiquement au démarrage. Il s'agit d'un fichier par répertoire, vous pouvez donc avoir différents fichiers pour différents projets.

Paul Beckingham
la source
1
Cela ne fonctionne pas réellement, j'obtiens "avertissement: save-tracepoints: aucun tracepoint à sauvegarder." Ceci malgré les points d'arrêt définis. Utilisation de gdb 6.8.
casualcoder
Cela fonctionne pour moi. GDB a besoin de la présence d'un .gdbinit global dans votre $ HOME / .gdbinit avec le contenu 'add-auto-load-safe-path /home/johnny/src/.gdbinit' et donc le dossier src / a également un .gdbinit séparé
truthadjustr
9

Une extension à l'extension d' Anon à la réponse de Johannes :

.gdbinit:

define bsave
    shell rm -f brestore.txt
    set logging file brestore.txt
    set logging on
    info break
    set logging off
    # Reformat on-the-fly to a valid GDB command file
    shell perl -n -e 'print "break $1\n" if /^\d+.+?(\S+)$/g' brestore.txt > brestore.gdb
end
document bsave
  store actual breakpoints
end

define brestore
  source brestore.gdb
end
document brestore
  restore breakpoints saved by bsave
end

Avec, brestorevous pouvez ensuite restaurer les points d'arrêt enregistrés avec bsave.

Dan Berindei
la source
Voici une meilleure regex: perl -ne "print \" break \ $ 1 \ n \ "if /at\s(.*:\d+)/" brestore.txt
George Godik
6

Extension à la réponse de Johannes : vous pouvez reformater automatiquement la sortie de info breakdans un fichier de commande GDB valide:

.gdbinit:

define bsave
   shell rm -f brestore.txt
   set logging file brestore.txt
   set logging on
   info break
   set logging off
   # Reformat on-the-fly to a valid gdb command file
   shell perl -n -e 'print "break $1\n" if /^\d+.+?(\S+)$/g' brestore.txt > brestore.gdb
end
document bsave
  store actual breakpoints
end

Ensuite, vous avez un fichier de commande valide dans brestore.gdb.

Cela a fonctionné pour moi lorsque l'application est compilée avec -g.

Je l'ai également testé avec succès avec GDB v6.8 sur Ubuntu 9.10 (Karmic Koala).

Peter Mortensen
la source
1
Merci pour cet extrait! Fonctionne très bien. Testé avec succès avec GNU gdb 6.3.50-20050815 (version Apple gdb-966) dans CarbonEmacs GNU Emacs 22.3.1 (i386-apple-darwin9.6.0, Carbon Version 1.6.0) sur Mac OS 10.5.8.
pestophage du
3

Mettez ce qui suit dans ~ / .gdbinit pour définir bsave et brestore comme commandes GDB pour enregistrer et restaurer les points d'arrêt.

define bsave
    save breakpoints ~/.breakpoints
end

define brestore
   source ~/.breakpoints
end
badeip
la source
1

avertissement: le protocole de sortie actuel ne prend pas en charge la redirection

J'obtiens également cette erreur / avertissement dans GDB lorsque j'essaye d'activer la journalisation en mode TUI . Cependant, la journalisation semble fonctionner en mode "non-TUI". Je quitte donc le mode TUI chaque fois que je veux enregistrer quelque chose. (Basculez d'avant en arrière en mode TUI avec Ctrl+X , Ctrl+A ).

Voici comment je travaille:

  1. démarrer GDB (en mode normal)
  2. activer la journalisation: set logging on- maintenant, il ne devrait pas se plaindre.
  3. basculer en arrière / en arrière en mode TUI et faire des choses GDB
  4. chaque fois que je veux enregistrer quelque chose (comme un énorme vidage de backtrace) - passer en mode normal
Magnux
la source
Oh, et si vous aimez utiliser "screen" (comme moi), cela deviendra un peu compliqué, car il utilise les mêmes raccourcis clavier.
Magnux
1

J'ai trouvé l'ajout suivant à une réponse précédente utile pour enregistrer / charger les points d'arrêt dans un fichier spécifique.

  • Enregistrer les points d'arrêt: bsave {filename}
  • Charger les points d'arrêt: bload {filename}

Comme dans la réponse précédente, ajoutez le code suivant au fichier ~ / .gdbinit

# Save breakpoints to a file
define bsave
    if $argc != 1
        help bsave
    else
    save breakpoints $arg0
    end
end
document bsave
Saves all current defined breakpoints to the defined file in the PWD
Usage: bsave <filename>
end

# Loads breakpoints from a file
define bload
    if $argc != 1
        help bload
    else
        source $arg0
    end
end
document bload
Loads all breakpoints from the defined file in the PWD
Usage: bload <filename>
end
Mark A
la source
0

Le problème est que la définition d'un point d'arrêt est sensible au contexte. Et si vous avez deux fonctions statiques nommées foo ?

Si vous déboguez déjà l'un des modules qui définit foo, alors GDB supposera que vous vouliez dire celui-là. Mais si vous videz simplement "break foo" dans un fichier et que vous lisez ensuite ce fichier au démarrage, la fonction foo que vous entendez ne sera pas claire .

Michael Snyder
la source
0

D'autres idées? j'ai

warning: Current output protocol does not support redirection

après

set logging on

ÉDITER:

Je sais que cette question est "comment enregistrer une liste de points d'arrêt", mais je viens de découvrir qu'avec GDB nous pouvons simplement définir des points d'arrêt "enregistrés dans un fichier" en

gdb> source breakpoints.txt

breakpoints.txtest un fichier comme celui-ci:

break main.cpp:25
break engine.cpp:465
break wheel.cpp:57
bruyant
la source