What are the best ways to automate a GDB debugging session?

Does GDB have a built in scripting mechanism, should I code up an expect script, or is there an even better solution out there?

I'll be sending the same sequence of commands every time and I'll be saving the output of each command to a file (most likely using GDB's built-in logging mechanism, unless someone has a better idea).


Solution 1:

Basically, in this example I wanted to get some variable values in particular places of the code; and have them output until the program crashes. So here is first a little program which is guaranteed to crash in a few steps, test.c:

#include <stdio.h>
#include <stdlib.h>

int icount = 1; // default value

main(int argc, char *argv[])
{
  int i;

  if (argc == 2) {
    icount = atoi(argv[1]);
  }

  i = icount;
  while (i > -1) {
    int b = 5 / i;
    printf(" 5 / %d = %d \n", i, b );
    i = i - 1;
  }

  printf("Finished\n");
  return 0;
}

The only reason the program accepts command-line arguments is to be able to choose the number of steps before crashing - and to show that gdb ignores --args in batch mode. This I compile with:

gcc -g test.c -o test.exe

Then, I prepare the following script - the main trick here is to assign a command to each breakpoint, which will eventually continue (see also Automate gdb: show backtrace at every call to function puts). This script I call test.gdb:

# http://sourceware.org/gdb/wiki/FAQ: to disable the
# "---Type <return> to continue, or q <return> to quit---"
# in batch mode:
set width 0
set height 0
set verbose off

# at entry point - cmd1
b main
commands 1
  print argc
  continue
end

# printf line - cmd2
b test.c:17
commands 2
  p i
  p b
  continue
end

# int b = line - cmd3
b test.c:16
commands 3
  p i
  p b
  continue
end

# show arguments for program
show args
printf "Note, however: in batch mode, arguments will be ignored!\n"

# note: even if arguments are shown;
# must specify cmdline arg for "run"
# when running in batch mode! (then they are ignored)
# below, we specify command line argument "2":
run 2     # run

#start # alternative to run: runs to main, and stops
#continue

Note that, if you intend to use it in batch mode, you have to "start up" the script at the end, with run or start or something similar.

With this script in place, I can call gdb in batch mode - which will generate the following output in the terminal:

$ gdb --batch --command=test.gdb --args ./test.exe 5
Breakpoint 1 at 0x804844d: file test.c, line 10.
Breakpoint 2 at 0x8048485: file test.c, line 17.
Breakpoint 3 at 0x8048473: file test.c, line 16.
Argument list to give program being debugged when it is started is "5".
Note, however: in batch mode, arguments will be ignored!

Breakpoint 1, main (argc=2, argv=0xbffff424) at test.c:10
10    if (argc == 2) {
$1 = 2

Breakpoint 3, main (argc=2, argv=0xbffff424) at test.c:16
16      int b = 5 / i;
$2 = 2
$3 = 134513899

Breakpoint 2, main (argc=2, argv=0xbffff424) at test.c:17
17      printf(" 5 / %d = %d \n", i, b );
$4 = 2
$5 = 2
 5 / 2 = 2 

Breakpoint 3, main (argc=2, argv=0xbffff424) at test.c:16
16      int b = 5 / i;
$6 = 1
$7 = 2

Breakpoint 2, main (argc=2, argv=0xbffff424) at test.c:17
17      printf(" 5 / %d = %d \n", i, b );
$8 = 1
$9 = 5
 5 / 1 = 5 

Breakpoint 3, main (argc=2, argv=0xbffff424) at test.c:16
16      int b = 5 / i;
$10 = 0
$11 = 5

Program received signal SIGFPE, Arithmetic exception.
0x0804847d in main (argc=2, argv=0xbffff424) at test.c:16
16      int b = 5 / i;

Note that while we specify command line argument 5, the loop still spins only two times (as is the specification of run in the gdb script); if run didn't have any arguments, it spins only once (the default value of the program) confirming that --args ./test.exe 5 is ignored.

However, since now this is output in a single call, and without any user interaction, the command line output can easily be captured in a text file using bash redirection, say:

gdb --batch --command=test.gdb --args ./test.exe 5 > out.txt

There is also an example of using python for automating gdb in c - GDB auto stepping - automatic printout of lines, while free running?

Hope this helps,
Cheers!

Solution 2:

gdb executes file .gdbinit after running. So you can add your commands to this file and see if it is OK for you. This is an example of .gdbinit in order to print backtrace for all f() calls:

set pagination off
set logging file gdb.txt
set logging on
file a.out
b f
commands
bt
continue
end
info breakpoints
r
set logging off
quit

Solution 3:

If a -x with a file is too much for you, just use multiple -ex's.

This is an example to track a running program showing (and saving) the backtrace on crashes

sudo gdb -p "$(pidof my-app)" -batch \
  -ex "set logging on" \
  -ex continue \
  -ex "bt full" \
  -ex quit