Как передать аргументы и перенаправить стандартный ввод из файла в программу, запущенную в GDB? - PullRequest
207 голосов
/ 23 декабря 2010

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

./a.out arg1 arg2 <file

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

Мне известна функциональность set args, но она работает только из приглашения gdb.

Ответы [ 5 ]

408 голосов
/ 23 декабря 2010

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

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

Волшебный бит: --args.

Просто введите run в командной консоли gdb для запуска отладки.

134 голосов
/ 23 декабря 2010

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

$ gdb ./a.out
(gdb) r < t
Starting program: /dir/a.out < t
4 голосов
/ 11 мая 2017

Если вы хотите иметь голую команду 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
1 голос
/ 06 ноября 2016

Запустите 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 main

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

    (gdb) r mulder / xfiles

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

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

0 голосов
/ 02 сентября 2018

Не было бы неплохо просто набрать 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... В этом сила Снарядов, привыкни!

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

  • 1000<&0 1001>&1 1002>&2 удаляет первые 3 FD
    • Предполагается, что 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 "$@" передает аргументы как указано

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

...