Wie übergebe ich Argumente und leite stdin von einer Datei an ein Programm um, das in gdb ausgeführt wird?

210

Normalerweise führe ich ein Programm aus als:

./a.out arg1 arg2 <file

Ich möchte es mit gdb debuggen.

Ich bin mir der set argsFunktionalität bewusst , aber das funktioniert nur über die GDB-Eingabeaufforderung.

Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功
quelle

Antworten:

136

Übergeben Sie die Argumente runaus gdb an den Befehl.

$ gdb ./a.out
(gdb) r < t
Starting program: /dir/a.out < t
Moinudin
quelle
3
rist die Abkürzung für runund Sie können ihm mit beliebigen Argumenten folgen. Wie in dieser Frage wäre es: r arg1 arg2 <fileoder es könnte seinrun arg1 arg2 <file
Phyatt
Bei mir funktioniert es nicht. Dann habe ich $ gdb ./a.outdann versucht, (gdb) r < t arg1 arg2was für mich gut funktioniert. In meinem Fall a.out = nft arg1 = import arg2 = json undt = file containing json rules
Mystictot
410

Du kannst das:

gdb --args path/to/executable -every -arg you can=think < of

Das magische Stückchen --args.

runGeben Sie einfach die gdb-Befehlskonsole ein, um das Debuggen zu starten.

rubenvb
quelle
24
Ich dachte, ich würde das zuerst falsch lesen; seltsam, dass --args vor der ausführbaren Datei steht. Aber so ist es!
Kaolin Feuer
8
@Kaolin --args muss vor der ausführbaren Datei stehen, da es sich um einen Switch für gdb handelt. Wenn es danach käme, wie würde gdb es von einem Argument unterscheiden, das Sie an die ausführbare Datei übergeben möchten, die Sie debuggen?
Codehippo
9
@codehippo: Wenn Sie nicht angegeben --argshaben, werden keine Argumente an die ausführbare Datei übergeben, daher ist dies kaum mehrdeutig.
Leichtigkeitsrennen im Orbit
14
Ich vermute, es liegt daran, dass herkömmlicherweise argv[0]der Name der ausführbaren Datei lautet
Claudiu
3
Dies wird die Eingabe von sich gdbselbst in die ofDatei umleiten und dazu führen, dass
GDB
4

Wenn Sie einen bloßen runBefehl gdbbenötigen, um Ihr Programm mit Umleitungen und Argumenten auszuführen, können Sie Folgendes verwenden set args:

% gdb ./a.out
(gdb) set args arg1 arg2 <file
(gdb) run

Ich war nicht in der Lage, das gleiche Verhalten mit --argsParametern zu erreichen , gdbentgeht den Umleitungen heftig, dh

% gdb --args echo 1 2 "<file"
(gdb) show args
Argument list to give program being debugged when it is started is "1 2 \<file".
(gdb) run
...
1 2 <file
...

Dieser leitet tatsächlich die Eingabe von gdb selbst um, nicht das, was wir hier wirklich wollen

% gdb --args echo 1 2 <file
zsh: no such file or directory: file
unkulunkulu
quelle
1

Starten Sie GDB für Ihr Projekt.

  1. Wechseln Sie in das Projektverzeichnis, in dem Sie die ausführbare Projektdatei bereits kompiliert haben. Geben Sie den Befehl gdb und den Namen der ausführbaren Datei wie folgt ein:

    gdb projectExecutablename

Dies startet gdb und druckt Folgendes: GNU gdb (Ubuntu 7.11.1-0ubuntu1 ~ 16.04) 7.11.1 Copyright (C) 2016 Freie Software Foundation, Inc. ............... .................................. Geben Sie "apropos word" ein, um nach Befehlen zu suchen, die sich auf "word" beziehen. Lesen von Symbolen aus projectExecutablename ... erledigt. (gdb)

  1. Bevor Sie Ihr Programm starten, möchten Sie Ihre Haltepunkte einrichten. Mit dem Befehl break können Sie dies tun. So setzen Sie einen Haltepunkt am Anfang der Funktion main:

    (gdb) b main

  2. Sobald Sie die Eingabeaufforderung (gdb) haben, startet der Befehl run die Ausführung der ausführbaren Datei. Wenn für das Programm, das Sie debuggen, Befehlszeilenargumente erforderlich sind, geben Sie diese im Befehl run an. Wenn Sie mein Programm für die Datei "xfiles" ausführen möchten (die sich in einem Ordner "mulder" im Projektverzeichnis befindet), gehen Sie wie folgt vor:

    (gdb) r mulder / xfiles

Hoffe das hilft.

Haftungsausschluss: Diese Lösung gehört nicht mir, sondern wurde von https://web.stanford.edu/class/cs107/guide_gdb.html angepasst. Diese kurze Anleitung zu gdb wurde höchstwahrscheinlich an der Stanford University entwickelt.

Ehsan
quelle
0

Wäre es nicht schön, einfach debugvor einem Befehl zu tippen , um ihn debuggen zu können?gdb auf Shell-Ebene ?

Darunter diese Funktion. Es funktioniert sogar mit folgenden:

"$program" "$@" < <(in) 1> >(out) 2> >(two) 3> >(three)

Dies ist ein Aufruf, bei dem Sie nichts steuern können, alles variabel ist, Leerzeichen, Zeilenvorschübe und Shell-Metazeichen enthalten kann. In diesem Beispiel in, out, twound threebeliebige andere Befehle , die konsumieren oder produzieren Daten , die müssen nicht geschadet.

Die folgende bashFunktion wird gdbin einer solchen Umgebung nahezu sauber aufgerufen [ Gist ]:

debug()
{
  1000<&0 1001>&1 1002>&2 \
  0</dev/tty 1>/dev/tty 2>&0 \
  /usr/bin/gdb -q -nx -nw \
  -ex 'set exec-wrapper /bin/bash -c "exec 0<&1000 1>&1001 2>&1002 \"\$@\"" exec' \
  -ex r \
  --args "$@";
}

Beispiel für die Anwendung: Geben Sie einfach debugvor:

Vor:

p=($'\n' $'I\'am\'evil' "  yay  ")
"b u g" "${p[@]}" < <(in) 1> >(out) 2> >(two) 3> >(three)

Nach dem:

p=($'\n' $'I\'am\'evil' "  yay  ")
debug "b u g" "${p[@]}" < <(in) 1> >(out) 2> >(two) 3> >(three)

Das ist es. Jetzt ist es ein Kinderspiel, mit zu debuggen gdb. Bis auf ein paar Details oder mehr:

  • gdbwird nicht automatisch beendet und hält daher die E / A-Umleitung offen, bis Sie beenden gdb. Aber ich nenne das eine Funktion.

  • Sie können nicht einfach argv0wie mit an das Programm übergeben exec -a arg0 command args. Folgendes sollte diesen Trick tun: Nach dem exec-wrapperWechsel "execzu "exec -a \"\${DEBUG_ARG0:-\$1}\".

  • Es sind FDs über 1000 offen, die normalerweise geschlossen sind. Wenn dies ein Problem ist, wechseln Sie 0<&1000 1>&1001 2>&1002zu Lesen0<&1000 1>&1001 2>&1002 1000<&- 1001>&- 1002>&-

  • Sie können nicht zwei Debugger gleichzeitig ausführen. Es kann auch Probleme geben, wenn ein anderer Befehl /dev/tty(oder STDIN) verwendet wird. Um dies zu beheben, ersetzen Sie /dev/ttydurch "${DEBUGTTY:-/dev/tty}". In einem anderen TTY-Typ tty; sleep infund verwenden Sie dann das gedruckte TTY (i. E. /dev/pts/60) zum Debuggen, wie in DEBUGTTY=/dev/pts/60 debug command arg... Das ist die Kraft von Shell, gewöhne dich daran!

Funktion erklärt:

  • 1000<&0 1001>&1 1002>&2 bewegt die ersten 3 FDs weg
    • Dies setzt voraus, dass die FDs 1000, 1001 und 1002 frei sind
  • 0</dev/tty 1>/dev/tty 2>&0stellt die ersten 3 FDs wieder her, die auf Ihre aktuelle TTY verweisen. So können Sie steuern gdb.
  • /usr/bin/gdb -q -nx -nwLäuft gdbAufrufe gdbauf Shell
  • -ex 'set exec-wrapper /bin/bash -c "exec 0<&1000 1>&1001 2>&1002 \"\$@\"" Erstellt einen Start-Wrapper, der die ersten 3 FDs wiederherstellt, die auf 1000 und höher gespeichert wurden
  • -ex r startet das Programm mit dem exec-wrapper
  • --args "$@" Übergibt die Argumente wie angegeben

War das nicht einfach?

Tino
quelle