Как передать аргументы и перенаправить стандартный ввод из файла в программу, запущенную в GDB?

210

Я обычно запускаю программу как:

./a.out arg1 arg2 <file

Я хотел бы отладить его с помощью GDB.

Я знаю о set argsфункциональности, но это работает только из приглашения GDB.

Сиро Сантилли 郝海东 冠状 病 六四 事件 法轮功
источник

Ответы:

136

Передайте аргументы runкоманде изнутри GDB.

$ gdb ./a.out
(gdb) r < t
Starting program: /dir/a.out < t
moinudin
источник
3
rэто сокращение, runи вы можете следовать за ним с любыми аргументами. Как и в этом вопросе, это было бы: r arg1 arg2 <fileили это может бытьrun arg1 arg2 <file
Phyatt
Для меня это не работает. Тогда я попытался $ gdb ./a.outтогда, (gdb) r < t arg1 arg2который работает хорошо для меня. В моем случае a.out = nft arg1 = import arg2 = json иt = file containing json rules
mystictot
410

Ты можешь сделать это:

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

Волшебное существо --args.

Просто введите runв командной консоли gdb, чтобы начать отладку.

rubenvb
источник
24
Сначала я подумал, что это неправильно; Странно, что --args идет перед исполняемым файлом. Но так оно и есть!
Каолин Огонь
8
@Kaolin --args должен стоять перед исполняемым файлом, потому что это ключ для gdb. Если это произойдет после того, как GDB будет отличать его от аргумента, который вы хотите передать в исполняемый файл, который вы отлаживаете?
codehippo
9
@codehippo: Ну, если вы не укажете, --argsто нет никаких аргументов, передаваемых в исполняемый файл, так что это вряд ли двусмысленно.
Гонки легкости на орбите
14
Я предполагаю, что это потому, что условно argv[0]это имя исполняемого файла
Claudiu
3
это перенаправит ввод самого gdbсебя в ofфайл и приведет к тому, что GDB попытается выполнить команды из него
unkulunkulu
4

Если вы хотите иметь пустую runкоманду gdbдля выполнения вашей программы с перенаправлениями и аргументами, вы можете использовать set args:

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

Я не смог добиться того же поведения с --argsпараметром, gdbяростно избегает перенаправления, т.е.

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

Это на самом деле перенаправляет ввод самого GDB, а не то, что мы действительно хотим здесь

% gdb --args echo 1 2 <file
zsh: no such file or directory: file
unkulunkulu
источник
1

Запустите GDB для вашего проекта.

  1. Перейдите в каталог проекта, где вы уже скомпилировали исполняемый файл проекта. Введите команду gdb и имя исполняемого файла, как показано ниже:

    gdb projectExecutablename

Это запускает GDB, печатает следующее: GNU GDB (Ubuntu 7.11.1-0ubuntu1 ~ 16.04) 7.11.1 Copyright (C) 2016 Free Software Foundation, Inc. ............... .................................. Введите "apropos word" для поиска команд, связанных с "word" .. Чтение символов из projectExecutablename ... сделано. (GDB)

  1. Перед запуском вашей программы вы хотите настроить точки останова. Команда break позволяет вам сделать это. Чтобы установить точку останова в начале функции с именем main:

    (GDB) B основной

  2. Когда у вас появляется приглашение (gdb), команда run запускает исполняемый файл. Если отлаживаемой программе требуются какие-либо аргументы командной строки, вы указываете их в команде run. Если вы хотите запустить мою программу в файле «xfiles» (который находится в папке «mulder» в каталоге проекта), вы должны сделать следующее:

    (gdb) r mulder / xfiles

Надеюсь это поможет.

Отказ от ответственности: это решение не мое, оно адаптировано из https://web.stanford.edu/class/cs107/guide_gdb.html Это краткое руководство по gdb, скорее всего, было разработано в Стэнфордском университете.

Ehsan
источник
0

Не было бы неплохо просто набрать debugперед любой командой, чтобы иметь возможность отладить ее gdbна уровне оболочки?

Под ним эта функция. Это даже работает со следующим:

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

Это вызов, когда вы не можете ничего контролировать, все переменное, может содержать пробелы, переводы строк и метасимволы оболочки. В этом примере in, out, twoи threeпроизвольные другие команды , которые потребляют или данные , которые не производят должен быть нанесен ущерб.

Следующая bashфункция вызывается gdbпочти чисто в такой среде [ 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 "$@";
}

Пример того, как применить это: Просто введите debugперед:

Перед:

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

После:

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

Вот и все. Теперь это абсолютно легкая задача для отладки gdb. За исключением нескольких деталей или более:

  • gdbне завершается автоматически и, следовательно, сохраняет перенаправление ввода-вывода открытым до выхода gdb. Но я называю это функцией.

  • Вы не можете легко перейти argv0к программе, как с exec -a arg0 command args. Следующие должны сделать этот трюк: После exec-wrapperизменения "execна "exec -a \"\${DEBUG_ARG0:-\$1}\".

  • Есть FD выше 1000 открытых, которые обычно закрыты. Если это проблема, перейдите 0<&1000 1>&1001 2>&1002к чтению0<&1000 1>&1001 2>&1002 1000<&- 1001>&- 1002>&-

  • Вы не можете запустить два отладчика параллельно. Также могут быть проблемы, если какая-то другая команда потребляет /dev/tty(или STDIN). Чтобы это исправить, замените /dev/ttyна "${DEBUGTTY:-/dev/tty}". В другом типе TTY, tty; sleep infа затем используйте напечатанный TTY (т.е. /dev/pts/60) для отладки, как в DEBUGTTY=/dev/pts/60 debug command arg... Это сила Shell, привыкнуть к этому!

Функция объяснила:

  • 1000<&0 1001>&1 1002>&2 уходит первые 3 ФД
    • Это предполагает, что FD 1000, 1001 и 1002 бесплатны
  • 0</dev/tty 1>/dev/tty 2>&0восстанавливает первые 3 FD, чтобы они указывали на ваш текущий TTY. Таким образом, вы можете контролироватьgdb .
  • /usr/bin/gdb -q -nx -nw работает gdb вызывает gdbна оболочке
  • -ex 'set exec-wrapper /bin/bash -c "exec 0<&1000 1>&1001 2>&1002 \"\$@\"" создает стартовую оболочку, которая восстанавливает первые 3 FD, которые были сохранены до 1000 и выше
  • -ex r запускает программу, используя exec-wrapper
  • --args "$@" передает аргументы как дано

Разве это не было легко?

Tino
источник