220

I usually run a program as :

./a.out arg1 arg2 <file

I would like to debug it using gdb.

I am aware of the set args functionality, but that only works from the gdb prompt.

Ciro Santilli OurBigBook.com
  • 347,512
  • 102
  • 1,199
  • 985

5 Answers5

414

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.

rubenvb
  • 74,642
  • 33
  • 187
  • 332
  • 25
    I thought I was reading this wrong at first; odd that --args goes before the executable. But so it is! – Kaolin Fire Jul 12 '13 at 23:11
  • 8
    @Kaolin --args must come before the executable because it is a switch for gdb. If it came after, how would gdb distinguish it from an argument you wished to pass into the executable you're debugging? – codehippo Aug 12 '13 at 20:25
  • 9
    @codehippo: Well, if you didn't specify `--args` then there _aren't_ any arguments passed to the executable, so it's hardly ambiguous. – Lightness Races in Orbit Jul 23 '14 at 14:02
  • 16
    I'm guessing it's because conventionally `argv[0]` is the name of the executable – Claudiu Sep 19 '14 at 18:15
  • It seems to have problems with arguments containing spaces. `GNU gdb (GDB) 7.8`, `CYGWIN_NT-6.1-WOW luna 1.7.35(0.287/5/3) 2015-03-04 12:07 i686 Cygwin` – rr- Mar 29 '15 at 12:59
  • @rr that would be the shell's problem: you need to ensure you quote enough (double and single quotes) so that the quotes you need survive the shell passing them to gdb. – rubenvb Jul 06 '15 at 15:32
  • I can't believe I didn't find out about this until now, this would have saved me little bits of time repeatedly over the past 10 years – Steven Lu Jan 16 '16 at 00:49
  • 2
    @Steven Lu From some obscure reason, gdb man doesn't contains info about the --args switch – Shmil The Cat Jan 31 '16 at 15:28
  • 9
    this will redirect input of `gdb` itself to the `of` file and result in gdb trying to execute commands from it – unkulunkulu May 11 '17 at 11:19
149

Pass the arguments to the run command from within gdb.

$ gdb ./a.out
(gdb) r < t
Starting program: /dir/a.out < t
moinudin
  • 134,091
  • 45
  • 190
  • 216
  • 6
    `r` is short for `run` and you can follow it with any arguments. Like in this question, it would be: `r arg1 arg2 – phyatt Jan 24 '17 at 14:45
  • For me it doesn't work. Then I tried `$ gdb ./a.out` then `(gdb) r < t arg1 arg2` which works fine for me. In my case `a.out = nft` `arg1 = import` `arg2 = json` and `t = file containing json rules` – Zzz0_o Aug 02 '17 at 10:27
7

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
unkulunkulu
  • 11,576
  • 2
  • 31
  • 49
1

Start GDB on your project.

  1. 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)

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

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

Ehsan
  • 1,338
  • 14
  • 13
1

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 exit gdb. But I call this a feature.

  • You cannot easily pass argv0 to the program like with exec -a arg0 command args. Following should do this trick: After exec-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 read 0<&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 type tty; sleep inf and then use the printed TTY (i. E. /dev/pts/60) for debugging, as in DEBUGTTY=/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 control gdb.
  • /usr/bin/gdb -q -nx -nw runs gdb invokes gdb 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 the exec-wrapper
  • --args "$@" passes the arguments as given

Wasn't that easy?

Tino
  • 9,583
  • 5
  • 55
  • 60