Powiedz, że mam dwa programy o nazwie bla i ret. Chcę debugować program blah, który odbiera dane wejściowe od ret programu poprzez przekierowanie I/O. Jak mogę debugować program blah w następującym przypadku, używając gdb?gdb - debugowanie z rurą
Odpowiedz
Na początku można uruchomić program i debugować go przez pid. To rozwiązanie oczywiście nie obejmuje wszystkich przypadków.
Innym podejściem jest wykorzystanie możliwości systemu Linux do komunikacji między procesami. W skrócie, przekierowujesz wyjście ret
do specjalnego pliku FIFO ("nazwany potok"), a następnie odczytujemy z niego FIFO za pomocą debuggera. Oto, jak to się robi. Z bash, wykonaj:
mkfifo foo
To tworzy specjalny plik w katalogu, który będzie służył jako nazwanego potoku. Kiedy piszesz tekst do tego pliku (używając tej samej składni echo "Hello" >foo
), program piszący będzie blokował, dopóki ktoś nie odczyta danych z pliku (na przykład cat <foo
). W naszym przypadku z tego pliku zostanie odczytany proces kontrolowany przez gdb.
Po utworzeniu fifo, uruchom z basha:
ret > foo & # ampersand because it may block as nobody is reading from foo
gdb blah
Następnie w wierszu gdb, uruchom
run <foo
i uzyskać pożądany efekt. Zauważ, że nie możesz odczytać danych z fifo (jak również z normalnej rury) dwa razy: po przeczytaniu wszystkich danych, proces blah
umiera i powinieneś powtórzyć pisanie polecenia do foo (możesz to zrobić z drugiego okna powłoki).
Kiedy skończysz, usuń FIFO z rm foo
(lub umieścić go w katalogu, w którym zostanie on automatycznie usunięty po ponownym uruchomieniu systemu, takich jak /tmp
).
Jeśli możesz sobie pozwolić na miejsce na dysku, możesz również po prostu włożyć je do zwykłego pliku 'foo', zamiast FIFO' foo' (oszczędza ci jedno polecenie :). – Frank
Zwykłe pliki i pliki FIFO/pipe mają inną semantykę dla read(). Jeśli osiągniesz EOF w zwykłym pliku, read() zwraca z może mniejszą ilością bajtów odczytanych niż określone. Jeśli czytasz z FIFO/pipe, read() blokuje dopóki nie nadejdzie określona liczba bajtów lub nie zakończy się proces zapisu do potoku. – SzG
Polecenie GDB run
używa bash
do wykonywania przekierowania. Prostym sposobem uzyskania odpowiednika ret | blah
jest użycie funkcji bash'a o nazwie process substitution.
$ gdb blah
...
(gdb) run < <(ret)
Objaśnienie: bash zastępuje <(ret)
z czymś /dev/fd/123
, który jest deskryptor pliku na standardowe wyjście z ret
. Możemy użyć tego fd podobnie do nazwanego FIFO, jak opisano w drugiej odpowiedzi, z tym że nie musimy ręcznie tworzyć go samodzielnie, ani martwić się o czas trwania procesu ret
.
Czy różni się to od: http://stackoverflow.com/questions/4521015/how-to-pass-arguments-and-redirect-stdin-from-a-file-to-program-run-in-gdb –