2012-05-25 13 views
49

GDB ha un meccanismo di scripting incorporato, dovrei programmare uno script previsto, o c'è una soluzione ancora migliore là fuori?Quali sono i modi migliori per automatizzare una sessione di debugging GDB?

Invierò sempre la stessa sequenza di comandi e salverò l'output di ciascun comando in un file (molto probabilmente utilizzando il meccanismo di registrazione incorporato di GDB, a meno che qualcuno non abbia un'idea migliore).

+0

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

risposta

43

gdb esegue il file .gdbinit dopo l'esecuzione. Quindi puoi aggiungere i tuoi comandi a questo file e vedere se è giusto per te. Questo è un esempio di .gdbinit per stampare backtrace per tutte le chiamate 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

Esiste una variabile ambientale che posso impostare per far sì che GDB esegua un file diverso all'avvio? – Anonymous

+18

@Anonimo no, ma esiste un'opzione della riga di comando: --command = FILE, -x Esegue i comandi GDB da FILE. – matt

64

Stavo solo passando attraverso qualcosa di simile, e si avvicinò con un esempio di base - e sapendo io dimentico presto, Ho pensato che sarebbe meglio pubblicarlo :) Quindi lo posterò qui, in quanto sembra relativo alla domanda.

Fondamentalmente, in questo esempio ho voluto ottenere alcuni valori variabili in particolari punti del codice; e farli emettere fino a quando il programma si blocca. Così qui è il primo di un piccolo programma che è guaranteed to crash in pochi passi, 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; 
} 

L'unica ragione per cui il programma accetta argomenti della riga di comando è quello di essere in grado di scegliere il numero di passi prima di schiantarsi - e per dimostrare che gdb ignora --args in modalità batch. Questo compilo con:

gcc -g test.c -o test.exe 

Poi, preparo il seguente script - il trucco principale è quello di assegnare un command ad ogni breakpoint, che alla fine continue (vedi anche Automate gdb: show backtrace at every call to function puts). Questo script chiamo 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 

Si noti che, se avete intenzione di usarlo in modalità batch, è necessario "start up" lo script alla fine, con run o start o qualcosa di simile.

Con questo script in atto, posso chiamare gdb in modalità batch - che genererà il seguente output nel terminale:

$ 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; 

Nota che, mentre si precisa linea di comando argomento 5, il ciclo gira ancora solo due volte (come è la specifica di run nello script gdb); se run non ha argomenti, ruota una sola volta (il valore predefinito del programma) confermando che --args ./test.exe 5 viene ignorato.

Tuttavia, dal momento che ora questo è uscita in una singola chiamata, e senza alcuna interazione da parte dell'utente, l'uscita di linea di comando può essere facilmente catturato in un file di testo utilizzando bash reindirizzamento, dicono:

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

C'è anche un esempio di utilizzo di python per l'automazione di gdb in c - GDB auto stepping - automatic printout of lines, while free running?

Spero che questo aiuti,
Cheers!

+3

Grazie per la condivisione, questo è utile –

+1

troppo buggato per me. 'detach' all'interno di' command' fa 'gdb' crash,' continue' all'interno di 'coammand' restituisce strani elementi' Selected thread is running'. – Blauhirn

1

Se un -x con un file è troppo per te, basta usare più -ex. Questo è un esempio per tracciare un programma in esecuzione che mostra (e salvare) la backtrace sui crash

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