Jak przekazywać argumenty i przekierowywać standardowe wejście z pliku do programu uruchomionego w gdb?

210

Zwykle uruchamiam program jako:

./a.out arg1 arg2 <file

Chciałbym debugować go za pomocą gdb.

Jestem świadomy tej set argsfunkcjonalności, ale działa to tylko z wiersza polecenia gdb.

Ciro Santilli
źródło

Odpowiedzi:

136

Przekaż argumenty do runpolecenia z poziomu gdb.

$ gdb ./a.out
(gdb) r < t
Starting program: /dir/a.out < t
moinudin
źródło
3
rjest skrótem runi możesz podążać za nim z dowolnymi argumentami. Jak w tym pytaniu, byłoby to: r arg1 arg2 <filealbo mogłoby byćrun arg1 arg2 <file
phyatt
Dla mnie to nie działa. Potem próbowałem $ gdb ./a.outnastępnie (gdb) r < t arg1 arg2który działa dobrze dla mnie. W moim przypadku a.out = nft arg1 = import arg2 = json it = file containing json rules
mystictot
410

Możesz to zrobić:

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

Magiczna istota --args.

Po prostu wpisz runw konsoli poleceń gdb, aby rozpocząć debugowanie.

rubenvb
źródło
24
Na początku myślałem, że źle to czytam; dziwne, że --args wyprzedza plik wykonywalny. Ale tak jest!
Kaolin Fire,
8
@Kaolin --args musi pojawić się przed plikiem wykonywalnym, ponieważ jest to przełącznik dla gdb. Gdyby to nastąpiło później, w jaki sposób gdb odróżniłby go od argumentu, który chciałbyś przekazać do wykonywalnego debugowania?
codehippo
9
@codehippo: Cóż, jeśli nie określiłeś, --argsnie ma żadnych argumentów przekazywanych do pliku wykonywalnego, więc nie jest to dwuznaczne.
Wyścigi lekkości na orbicie
14
Domyślam się, że to dlatego, że konwencjonalnie argv[0]jest to nazwa pliku wykonywalnego
Claudiu
3
spowoduje to przekierowanie gdbsamego wejścia do ofpliku i spowoduje, że gdb spróbuje wykonać z niego polecenia
unkulunkulu
4

Jeśli chcesz mieć nagie runpolecenie gdbdo wykonania programu z przekierowaniami i argumentami, możesz użyć set args:

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

Nie byłem w stanie osiągnąć tego samego zachowania z --argsparametrem, gdbzaciekle ucieka przed przekierowaniami, tj

% 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
...

Ten faktycznie przekierowuje wejście samego gdb, a nie to, czego naprawdę chcemy tutaj

% gdb --args echo 1 2 <file
zsh: no such file or directory: file
unkulunkulu
źródło
1

Uruchom GDB w swoim projekcie.

  1. Przejdź do katalogu projektu, w którym skompilowałeś już plik wykonywalny projektu. Wydaj polecenie gdb i nazwę pliku wykonywalnego, jak poniżej:

    gdb projectExecutablename

Uruchamia to gdb, drukuje następujące: GNU gdb (Ubuntu 7.11.1-0ubuntu1 ~ 16.04) 7.11.1 Copyright (C) 2016 Free Software Foundation, Inc. ............... .................................. Wpisz „apropos word”, aby wyszukać polecenia związane z „word” .. Odczytywanie symboli z projektuExecutablename ... gotowe. (gdb)

  1. Przed uruchomieniem programu należy skonfigurować punkty przerwania. Polecenie break pozwala ci to zrobić. Aby ustawić punkt przerwania na początku funkcji o nazwie main:

    (gdb) b główny

  2. Po wyświetleniu monitu (gdb) polecenie Uruchom uruchamia plik wykonywalny. Jeśli program, który debugujesz, wymaga argumentów wiersza polecenia, podajesz je w poleceniu uruchomienia. Jeśli chcesz uruchomić mój program na pliku „xfiles” (który znajduje się w folderze „mulder” w katalogu projektu), wykonaj następujące czynności:

    (gdb) r mulder / xfiles

Mam nadzieję że to pomoże.

Oświadczenie: To rozwiązanie nie jest moje, zostało zaadaptowane z https://web.stanford.edu/class/cs107/guide_gdb.html Ten krótki przewodnik po gdb został najprawdopodobniej opracowany na Uniwersytecie Stanforda.

Ehsan
źródło
0

Czy nie byłoby miło napisać debugprzed jakimkolwiek poleceniem, aby móc je debugować gdbna poziomie powłoki?

Poniżej tej funkcji. Działa nawet z następującymi:

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

Jest to wywołanie, w którym nie można nic kontrolować, wszystko jest zmienne, może zawierać spacje, linie i metaznaki powłoki. W tym przykładzie in, out, twoi threesą dowolne inne polecenia, które pochłaniają i dane produkty, które nie może zostać poszkodowana.

Następująca bashfunkcja wywołuje gdbprawie czysto w takim środowisku [ 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 "$@";
}

Przykład zastosowania: Po prostu wpisz debugz przodu:

Przed:

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

Po:

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

Otóż ​​to. Teraz debugowanie jest absolutnie oczywiste gdb. Z wyjątkiem kilku szczegółów lub więcej:

  • gdbnie kończy się automatycznie, a zatem utrzymuje przekierowanie we / wy otwarte do momentu wyjścia gdb. Ale nazywam to funkcją.

  • Nie możesz łatwo przejść argv0do programu tak jak w przypadku exec -a arg0 command args. Następujący powinien wykonać tę sztuczkę: Po exec-wrapperzmianie "execna "exec -a \"\${DEBUG_ARG0:-\$1}\".

  • Istnieją FD powyżej 1000 otwarte, które są normalnie zamknięte. Jeśli to jest problem, zmień 0<&1000 1>&1001 2>&1002na „czytaj”0<&1000 1>&1001 2>&1002 1000<&- 1001>&- 1002>&-

  • Nie można uruchomić dwóch debuggerów równolegle. Mogą również występować problemy, jeśli jakieś inne polecenie zużywa /dev/tty(lub STDIN). Aby to naprawić, wymienić /dev/ttysię "${DEBUGTTY:-/dev/tty}". W niektórych innych typach TTY, tty; sleep infa następnie użyj drukowanego TTY (i. E. /dev/pts/60) do debugowania, jak w DEBUGTTY=/dev/pts/60 debug command arg... To jest Moc Powłoki, przyzwyczaj się do tego!

Funkcja wyjaśniona:

  • 1000<&0 1001>&1 1002>&2 odsuwa pierwsze 3 FD
    • Zakłada się, że FD 1000, 1001 i 1002 są bezpłatne
  • 0</dev/tty 1>/dev/tty 2>&0przywraca pierwsze 3 FD wskazujące na twoją obecną TTY. Więc możesz kontrolować gdb.
  • /usr/bin/gdb -q -nx -nwuruchamia gdbwywołania gdbna powłoce
  • -ex 'set exec-wrapper /bin/bash -c "exec 0<&1000 1>&1001 2>&1002 \"\$@\"" tworzy opakowanie startowe, które przywraca pierwsze 3 FD, które zostały zapisane do 1000 i więcej
  • -ex r uruchamia program za pomocą exec-wrapper
  • --args "$@" przekazuje argumenty jak podano

Czy to nie było łatwe?

Tino
źródło