2009-09-21 27 views
35

Sagen wir, ich habe zwei Programme namens blah und ret. Ich möchte blah Programm debuggen, die Eingabe von ret Programm über I/O-Umleitung erhält. Wie debugge ich das Programm blah im folgenden Fall mit gdb?gdb - debugging mit Rohr

bash> ret | blah 
+0

Ist das anders als: http://stackoverflow.com/questions/4521015/how-to-pass-arguments-and-redirect-stdin-from-a-file-to-program-run-in-gdb –

Antwort

41

Zuerst können Sie das Programm ausführen und es mit PID debuggen. Diese Lösung deckt natürlich nicht alle Fälle ab.

Ein anderer Ansatz ist die Verwendung von Linux-Funktionen für die Kommunikation zwischen Prozessen. Kurz gesagt, Sie leiten die Ausgabe von ret in eine FIFO-Spezialdatei ("named pipe") um und lesen dann aus diesem FIFO über den Debugger. Hier ist, wie es gemacht wird. Von bash, laufen:

mkfifo foo 

Dies schafft eine spezielle Datei in Ihrem Verzeichnis, das als Named Pipe dienen. Wenn Sie Text in diese Datei schreiben (mit derselben Syntax echo "Hello" >foo), wird das Schreibprogramm blockiert, bis jemand die Daten aus der Datei liest (z. B. cat <foo). In unserem Fall wird ein von gdb gesteuerter Prozess aus dieser Datei lesen.

Nachdem Sie eine Fifo erstellt von bash ausführen:

ret > foo & # ampersand because it may block as nobody is reading from foo 
gdb blah 

Dann in gdb Aufforderung führen

run <foo 

und die gewünschte Wirkung erzielen. Beachten Sie, dass Sie die Daten vom FIFO (sowie von einer normalen Pipe) nicht zweimal lesen können: Wenn Sie alle Daten gelesen haben, stirbt der blah Prozess und Sie sollten den Befehl zum Schreiben an foo wiederholen (Sie können es tun aus dem anderen Shell-Fenster).

Wenn Sie fertig sind, entfernen Sie den Fifo mit rm foo (oder legen Sie es in das Verzeichnis, in dem es automatisch beim Systemneustart entfernt wird, z. B. /tmp).

+1

Wenn Sie sich den Speicherplatz leisten können, können Sie ihn auch in eine normale Datei 'foo' pipen, anstatt in einen FIFO' foo' (speichert einen Befehl :). – Frank

+7

Reguläre Dateien und FIFOs/Pipes haben unterschiedliche Semantiken für read(). Wenn Sie EOF in einer regulären Datei erreichen, wird read() mit möglicherweise weniger gelesenen Bytes als angegeben zurückgegeben. Wenn Sie von einem FIFO/einer Pipe lesen, lesen Sie() solange, bis die angegebene Anzahl an Bytes eintrifft oder der Prozess, der in die Pipe geschrieben wurde, beendet wurde. – SzG

9

Der Befehl run von GDB verwendet bash, um die Umleitung auszuführen. Eine einfache Möglichkeit, das Äquivalent von ret | blah zu erreichen, ist die Verwendung der Bash-Funktion process substitution.

$ gdb blah 
... 
(gdb) run < <(ret) 

Erläuterung: bash ersetzt <(ret) mit so etwas wie /dev/fd/123, die ein Dateideskriptor des stdout von ret ist. Wir können dieses fd ähnlich einem benannten FIFO verwenden, wie in der anderen Antwort beschrieben, außer dass wir es nicht manuell selbst erstellen müssen, oder uns um die Lebensdauer des ret Prozesses sorgen müssen.

+0

Passt genau zu meinen Bedürfnissen, danke. – Limeth

+0

Dies funktioniert nicht für zsh. Gibt es eine Alternative? – redfast00

+0

Prozesssubstitution funktioniert in zsh genauso wie in bash. Wie lautet Ihr Aufruf und welche Fehlermeldung erhalten Sie? –