91 votes

Automatisation des sessions GDB

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).

109voto

sdaau Points 6262

Je viens de passer par quelque chose de similaire, et est venu avec un exemple de base - et en sachant que je vais oublier très vite, j'ai pensé que je ferais mieux de poster :) Donc je vais le poster ici, car il ressemble trait à la question.

En gros, dans cet exemple, je voulais obtenir quelques valeurs de variables dans des endroits en particulier, du code; et leur production jusqu'à ce que le programme se bloque. Donc, ici, est d'abord un petit programme qui est garanti pour crash 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 d'être en mesure de choisir le nombre d'étapes avant de s'écraser et de montrer qu' 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 ici est d'attribuer un command chaque breakpoint, qui finira par continue (voir également Automatiser gdb: afficher le backtrace à chaque appel de fonction met). Ce script je l'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 "start up" 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 - qui produira 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;

Note que bien que nous spécifier l'argument de ligne de commande 5, la boucle a toujours tourne à seulement deux fois (comme c'est la spécification de l' run dans la gdb script); if run n'ont pas d'arguments, elle fait tourner qu'une seule fois (la valeur par défaut du programme) confirmant qu' --args ./test.exe 5 est ignoré.

Cependant, puisque maintenant c'est la sortie en un seul appel, et sans aucune interaction de l'utilisateur, la sortie de ligne de commande peut être facilement capturés dans un fichier texte à l'aide de bash redirection, dire:

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

Il est aussi un exemple de l'utilisation de python pour automatiser gdb c - GDB automatique pas à pas - impression automatique des lignes, tandis que le free-running?

Espérons que cela aide,
Cheers!

81voto

skwllsp Points 9661

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 le retour en arrière pour tous les f() appels:

 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
 

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X