web-dev-qa-db-fra.com

Quels sont les meilleurs moyens d'automatiser une session de débogage GDB?

GDB a-t-il un mécanisme de script intégré? Devrais-je coder un script attendu ou existe-t-il une solution encore meilleure?

J'enverrai la même séquence de commandes à chaque fois et je sauvegarderai le résultat de chaque commande dans un fichier (le plus probablement en utilisant le mécanisme de journalisation intégré de GDB, à moins que quelqu'un n'ait une meilleure idée).

60
Anonymous

gdb exécute le fichier .gdbinit après son exécution. Vous pouvez donc ajouter vos commandes à ce fichier et voir si cela vous convient. Ceci est un exemple de .gdbinit Afin d'imprimer la trace pour tous les appels f():

set pagination off
set logging file gdb.txt
set logging on
file a.out
b f
commands
bt
continue
end
info breakpoints
r
set logging off
quit
57
Sergei Kurenkov

Je passais juste à travers quelque chose de similaire, et suis venu avec un exemple de base - et sachant que je l'oublierai bientôt, j'ai pensé que je ferais mieux de le poster :) Je vais donc le poster ici, car il semble lié à la question.

Fondamentalement, dans cet exemple, je voulais obtenir des valeurs de variable à des endroits particuliers du code; et les avoir sortie jusqu'à ce que le programme se bloque. Donc, voici d’abord un petit programme qui est avec un crash garanti en quelques étapes, test.c:

#include <stdio.h>
#include <stdlib.h>

int icount = 1; // default value

main(int argc, char *argv[])
{
  int i;

  if (argc == 2) {
    icount = atoi(argv[1]);
  }

  i = icount;
  while (i > -1) {
    int b = 5 / i;
    printf(" 5 / %d = %d \n", i, b );
    i = i - 1;
  }

  printf("Finished\n");
  return 0;
}

La seule raison pour laquelle le programme accepte les arguments de ligne de commande est la possibilité de choisir le nombre d'étapes avant de planter - et de montrer que gdb ignore --args en mode batch. Ce que je compile avec:

gcc -g test.c -o test.exe

Ensuite, je prépare le script suivant. L’astuce consiste ici à affecter un command à chaque breakpoint, qui finira par continue (voir aussi Automate gdb: afficher la trace à chaque appel à une fonction met) ). Ce script, j’appelle test.gdb:

# http://sourceware.org/gdb/wiki/FAQ: to disable the
# "---Type <return> to continue, or q <return> to quit---"
# in batch mode:
set width 0
set height 0
set verbose off

# at entry point - cmd1
b main
commands 1
  print argc
  continue
end

# printf line - cmd2
b test.c:17
commands 2
  p i
  p b
  continue
end

# int b = line - cmd3
b test.c:16
commands 3
  p i
  p b
  continue
end

# show arguments for program
show args
printf "Note, however: in batch mode, arguments will be ignored!\n"

# note: even if arguments are shown;
# must specify cmdline arg for "run"
# when running in batch mode! (then they are ignored)
# below, we specify command line argument "2":
run 2     # run

#start # alternative to run: runs to main, and stops
#continue

Notez que si vous avez l’intention de l’utiliser en mode batch, vous devez "lancer" le script à la fin, avec run ou start ou quelque chose de similaire.

Avec ce script en place, je peux appeler gdb en mode batch, ce qui générera la sortie suivante dans le terminal:

$ gdb --batch --command=test.gdb --args ./test.exe 5
Breakpoint 1 at 0x804844d: file test.c, line 10.
Breakpoint 2 at 0x8048485: file test.c, line 17.
Breakpoint 3 at 0x8048473: file test.c, line 16.
Argument list to give program being debugged when it is started is "5".
Note, however: in batch mode, arguments will be ignored!

Breakpoint 1, main (argc=2, argv=0xbffff424) at test.c:10
10    if (argc == 2) {
$1 = 2

Breakpoint 3, main (argc=2, argv=0xbffff424) at test.c:16
16      int b = 5 / i;
$2 = 2
$3 = 134513899

Breakpoint 2, main (argc=2, argv=0xbffff424) at test.c:17
17      printf(" 5 / %d = %d \n", i, b );
$4 = 2
$5 = 2
 5 / 2 = 2 

Breakpoint 3, main (argc=2, argv=0xbffff424) at test.c:16
16      int b = 5 / i;
$6 = 1
$7 = 2

Breakpoint 2, main (argc=2, argv=0xbffff424) at test.c:17
17      printf(" 5 / %d = %d \n", i, b );
$8 = 1
$9 = 5
 5 / 1 = 5 

Breakpoint 3, main (argc=2, argv=0xbffff424) at test.c:16
16      int b = 5 / i;
$10 = 0
$11 = 5

Program received signal SIGFPE, Arithmetic exception.
0x0804847d in main (argc=2, argv=0xbffff424) at test.c:16
16      int b = 5 / i;

Notez que si nous spécifions l'argument 5 de la ligne de commande, la boucle ne tourne toujours que deux fois (comme la spécification de run dans le script gdb.); si run n'a pas d'argument, il ne tourne qu'une fois (valeur par défaut du programme), confirmant que --args ./test.exe 5 est ignoré.

Cependant, étant donné que maintenant ceci est sorti en un seul appel, et sans aucune interaction de l'utilisateur, la sortie en ligne de commande peut facilement être capturée dans un fichier texte en utilisant la redirection bash, par exemple:

gdb --batch --command=test.gdb --args ./test.exe 5 > out.txt

Il existe également un exemple d’utilisation de python pour l’automatisation de gdb dans c - GDB auto-progression - impression automatique des lignes, lors de l’exécution libre?

J'espère que cela t'aides,
À votre santé!

77
sdaau

Si un -x avec un fichier est trop pour vous, utilisez simplement plusieurs -ex. Ceci est un exemple pour suivre un programme en cours affichant (et enregistrant) la trace arrière en cas de blocage.

Sudo gdb -p $(pidof my-app) -batch \
  -ex "set logging on" \
  -ex continue \
  -ex "bt full" \
  -ex quit
8
Treviño