2012-05-25 12 views
49

¿Tiene GDB un mecanismo de scripting integrado, debería codificar un script esperado, o hay una solución aún mejor por ahí?¿Cuáles son las mejores formas de automatizar una sesión de depuración de GDB?

Enviaré la misma secuencia de comandos cada vez y guardaré la salida de cada comando en un archivo (lo más probable es que use el mecanismo de registro integrado de GDB, a menos que alguien tenga una idea mejor).

+0

subconjunto: http://stackoverflow.com/questions/13935443/gdb-scripting-execute-commands-at-selected- breakpoint –

Respuesta

43

gdb ejecuta el archivo .gdbinit después de ejecutar. Para que pueda agregar sus comandos a este archivo y ver si está bien para usted. Este es un ejemplo de .gdbinit con el fin de imprimir traza para todas las llamadas 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 
+1

¿Existe una variable ambiental que pueda establecer que haga que GDB ejecute un archivo diferente al inicio? – Anonymous

+18

@Anonymous no, pero hay una opción de línea de comando: --command = FILE, -x Ejecutar comandos GDB desde FILE. – matt

64

sólo iba por algo similar, y se acercó con un ejemplo básico - y sabiendo que voy a olvidar pronto, Pensé que sería mejor que lo publicara :) Así que lo publicaré aquí, ya que parece relacionado con la pregunta.

Básicamente, en este ejemplo, quería obtener algunos valores variables en lugares específicos del código; y hacer que salgan hasta que el programa falle. Así que aquí es en primer lugar un pequeño programa que es guaranteed to crash en unos pocos pasos, 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 única razón el programa acepta los argumentos de línea de comandos es ser capaz de elegir el número de pasos antes de caer - y mostrar que gdb ignora --args en modo de proceso por lotes. Este compilo con:

gcc -g test.c -o test.exe 

Entonces, preparar la siguiente secuencia de comandos - el truco principal aquí es asignar un command a cada breakpoint, que con el tiempo continue (véase también Automate gdb: show backtrace at every call to function puts). Este script que llamo 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 

Tenga en cuenta que, si la intención de usarlo en el modo por lotes, lo que tiene que "poner en marcha" el guión al final, con run o start o algo similar.

Con este script en su lugar, puedo llamar gdb en modo batch - que generará la siguiente salida en el 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; 

Tenga en cuenta que mientras que especificamos comando argumento de la línea 5, el bucle todavía sólo giros dos veces (como es la especificación de run en el script gdb); si run no tiene ningún argumento, gira solo una vez (el valor predeterminado del programa) confirmando que --args ./test.exe 5 se ignora.

Sin embargo, ya que ahora se trata de la producción en una sola llamada, y sin ninguna interacción del usuario, la salida de línea de comandos puede ser fácilmente capturado en un archivo de texto usando bash redirección, dicen:

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

También hay un ejemplo de usar python para automatizar gdb en c - GDB auto stepping - automatic printout of lines, while free running?

Espero que esto ayude,
¡Salud!

+3

Gracias por compartir, esto es útil –

+1

demasiado problemático para mí. 'detach' dentro de' command' hace que 'gdb' crash,' continue' dentro de 'coammand' arroje como resultado la existencia de alertas 'thread thread is running'. – Blauhirn

1

Si a -x con un archivo es demasiado para ti, simplemente usa múltiples -ex. Este es un ejemplo para el seguimiento de un programa en ejecución que muestra (y el ahorro) la traza de accidentes

sudo gdb -p $(pidof my-app) -batch \ 
    -ex "set logging on" \ 
    -ex continue \ 
    -ex "bt full" \ 
    -ex quit 
Cuestiones relacionadas