How to pass arguments and redirect stdin from a file to program run in gdb?
Solution 1:
You can do this:
gdb --args path/to/executable -every -arg you can=think < of
The magic bit being --args
.
Just type run
in the gdb command console to start debugging.
Solution 2:
Pass the arguments to the run
command from within gdb.
$ gdb ./a.out
(gdb) r < t
Starting program: /dir/a.out < t
Solution 3:
If you want to have bare run
command in gdb
to execute your program with redirections and arguments, you can use set args
:
% gdb ./a.out
(gdb) set args arg1 arg2 <file
(gdb) run
I was unable to achieve the same behaviour with --args
parameter, gdb
fiercely escapes the redirections, i.e.
% 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
...
This one actually redirects the input of gdb itself, not what we really want here
% gdb --args echo 1 2 <file
zsh: no such file or directory: file
Solution 4:
Start GDB on your project.
-
Go to project directory, where you've already compiled the project executable. Issue the command gdb and the name of the executable as below:
gdb projectExecutablename
This starts up gdb, prints the following: GNU gdb (Ubuntu 7.11.1-0ubuntu1~16.04) 7.11.1 Copyright (C) 2016 Free Software Foundation, Inc. ................................................. Type "apropos word" to search for commands related to "word"... Reading symbols from projectExecutablename...done. (gdb)
-
Before you start your program running, you want to set up your breakpoints. The break command allows you to do so. To set a breakpoint at the beginning of the function named main:
(gdb) b main
-
Once you've have the (gdb) prompt, the run command starts the executable running. If the program you are debugging requires any command-line arguments, you specify them to the run command. If you wanted to run my program on the "xfiles" file (which is in a folder "mulder" in the project directory), you'd do the following:
(gdb) r mulder/xfiles
Hope this helps.
Disclaimer: This solution is not mine, it is adapted from https://web.stanford.edu/class/cs107/guide_gdb.html This short guide to gdb was, most probably, developed at Stanford University.
Solution 5:
Wouldn't it be nice to just type debug
in front of any command to be able to debug it with gdb
on shell level?
Below it this function. It even works with following:
"$program" "$@" < <(in) 1> >(out) 2> >(two) 3> >(three)
This is a call where you cannot control anything, everything is variable, can contain spaces, linefeeds and shell metacharacters. In this example, in
, out
, two
, and three
are arbitrary other commands which consume or produce data which must not be harmed.
Following bash
function invokes gdb
nearly cleanly in such an environment [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 "$@";
}
Example on how to apply this: Just type debug
in front:
Before:
p=($'\n' $'I\'am\'evil' " yay ")
"b u g" "${p[@]}" < <(in) 1> >(out) 2> >(two) 3> >(three)
After:
p=($'\n' $'I\'am\'evil' " yay ")
debug "b u g" "${p[@]}" < <(in) 1> >(out) 2> >(two) 3> >(three)
That's it. Now it's an absolute no-brainer to debug with gdb
. Except for a few details or more:
gdb
does not quit automatically and hence keeps the IO redirection open until you exitgdb
. But I call this a feature.You cannot easily pass
argv0
to the program like withexec -a arg0 command args
. Following should do this trick: Afterexec-wrapper
change"exec
to"exec -a \"\${DEBUG_ARG0:-\$1}\"
.There are FDs above 1000 open, which are normally closed. If this is a problem, change
0<&1000 1>&1001 2>&1002
to read0<&1000 1>&1001 2>&1002 1000<&- 1001>&- 1002>&-
You cannot run two debuggers in parallel. There also might be issues, if some other command consumes
/dev/tty
(or STDIN). To fix that, replace/dev/tty
with"${DEBUGTTY:-/dev/tty}"
. In some other TTY typetty; sleep inf
and then use the printed TTY (i. E./dev/pts/60
) for debugging, as inDEBUGTTY=/dev/pts/60 debug command arg..
. That's the Power of Shell, get used to it!
Function explained:
-
1000<&0 1001>&1 1002>&2
moves away the first 3 FDs- This assumes, that FDs 1000, 1001 and 1002 are free
-
0</dev/tty 1>/dev/tty 2>&0
restores the first 3 FDs to point to your current TTY. So you can controlgdb
. -
/usr/bin/gdb -q -nx -nw
runsgdb
invokesgdb
on shell -
-ex 'set exec-wrapper /bin/bash -c "exec 0<&1000 1>&1001 2>&1002 \"\$@\""
creates a startup wrapper, which restores the first 3 FDs which were saved to 1000 and above -
-ex r
starts the program using theexec-wrapper
-
--args "$@"
passes the arguments as given
Wasn't that easy?