2012-05-25 12 views
49

Hat GDB einen eingebauten Scripting-Mechanismus, sollte ich ein Expect-Skript kodieren, oder gibt es eine noch bessere Lösung?Was sind die besten Möglichkeiten, um eine GDB-Debugging-Sitzung zu automatisieren?

Ich werde jedes Mal die gleiche Befehlsfolge senden, und ich werde die Ausgabe jedes Befehls in eine Datei speichern (höchstwahrscheinlich mithilfe des integrierten Logging-Mechanismus von GDB, es sei denn, jemand hat eine bessere Idee).

+0

Subset zu verfolgen: http://stackoverflow.com/questions/13935443/gdb-scripting-execute-commands-at-selected- Haltepunkt –

Antwort

43

gdb führt Datei .gdbinit nach dem Ausführen aus. So können Sie Ihre Befehle zu dieser Datei hinzufügen und sehen, ob es für Sie in Ordnung ist. Dies ist ein Beispiel für .gdbinit um Backtrace für alle f() Anrufe zu drucken:

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

Gibt es eine Umgebungsvariable, die ich festlegen kann, die GDB beim Start eine andere Datei ausführen lässt? – Anonymous

+18

@Anonymous Nein, aber es gibt eine Befehlszeilenoption: --command = FILE, -x Führen Sie GDB-Befehle von FILE. – matt

64

ich nur durch ähnlich etwas los war, und kam mit einem einfachen Beispiel auf - und zu wissen, ich werde es bald vergessen, Ich dachte, ich sollte es besser posten :) Also werde ich es hier posten, wie es im Zusammenhang mit der Frage aussieht.

Grundsätzlich wollte ich in diesem Beispiel einige Variablenwerte an bestimmten Stellen des Codes erhalten; und lassen Sie sie ausgeben, bis das Programm abstürzt. Hier ist also zunächst ein kleines Programm, das guaranteed to crash in wenigen Schritten ist, 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; 
} 

Der einzige Grund, das Programm Befehlszeilenargumente akzeptiert, ist in der Lage, die Anzahl der Schritte zu wählen, vor dem Absturz - und zu zeigen, dass gdb ignoriert --args im Batch-Modus. Das habe ich kompilieren mit:

gcc -g test.c -o test.exe 

Dann bereite ich das folgende Skript - der wichtigste Trick hier ist eine command zu jedem breakpoint zuweisen, die continue schließlich wird (siehe auch Automate gdb: show backtrace at every call to function puts). Dieses Skript I test.gdb nennen:

# 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 

Beachten Sie, dass, wenn Sie es im Batch-Modus verwenden möchten, müssen Sie „Start-up“ das Skript am Ende, mit run oder start oder etwas ähnliches.

Mit diesem Skript an Ort und Stelle, kann ich gdb im Batch-Modus aufrufen - was die folgende Ausgabe im Terminal erzeugen:

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

Beachten Sie, dass, während wir Befehlszeilenargument 5, die Schleife nur noch angeben, dreht zwei Mal (wie ist die Spezifikation von run in der gdb Skript); Wenn run keine Argumente hatte, spinnt es nur einmal (der Standardwert des Programms) und bestätigt, dass --args ./test.exe 5 ignoriert wird.

Da jedoch nun diese Ausgabe in einem einzigen Aufruf ist, und ohne Benutzereingriff kann die Kommandozeile ausgegeben leicht in einer Textdatei mit bash Umleitung erfaßt werden, sagen:

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

Es ist auch Ein Beispiel für die Verwendung von Python zur Automatisierung von gdb in c - GDB auto stepping - automatic printout of lines, while free running?

Hoffen, dass dies hilft,
Prost!

+3

Danke für den Austausch, das ist nützlich –

+1

zu buggy für mich. 'detach' innerhalb von' command' lässt 'gdb' zum Absturz bringen,' continue' in 'coammand' führt zu seltsamen' Selected thread is running' Alerts. – Blauhirn

1

Wenn ein -x mit einer Datei zu viel für Sie ist, verwenden Sie einfach multiple -ex's. Dies ist ein Beispiel ein laufendes Programm zeigt (und Speicher), um die Backtrace auf Abstürze

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