Showing posts with label GDB. Show all posts
Showing posts with label GDB. Show all posts

Run Python script in GDB

Recent GDB (at least afeter version 7) can run Python script. To run it, we use source command as same as the GDB macro.

Let's try it. We prepare the following Python script.
$ cat hello.py
#!/usr/bin/env python
import sys
sys.stdout.write('Hello, my first script.\n')
Launch GDB and run the script
(gdb) source hello.py
Hello, my first script.

Use of GDB functions from a Python script

The following is the example to use GDB functions from a Python script. gdb.execute() can run operations used in the GDB command line.

The following example uses target.cc as a debug target.
[target.cc]
#include <cstdio>
#include <cstdlib>
#include <time.h>

int getval(int div)
{
        return time(NULL) / div;
}

int main(void)
{
        printf("val: %d\n", getval(5));
        return EXIT_SUCCESS;
}
show-bt.py will perform the following 4 operations.
  • Set a break point at the head of getval() function
  • Run the program
  • Show the bracktrace at the break point
  • Show rax register at the break point
[show-bt.py] 
gdb.execute('b getval')
gdb.execute('run')
gdb.execute('bt')
gdb.execute('p/x $rax')
The following is an example to run a script in the command line. The command line argument '-q' disables to show startup messages of GDB such as copyright. '-x' specifies the script to be executed.
$ gdb -q -x show-bt.py  target
Reading symbols from /home/foo/target...done.
Breakpoint 1 at 0x400627: file target.cc, line 7.

Breakpoint 1, getval (div=5) at target.cc:7
7               return time(NULL) / div;
#0  getval (div=5) at target.cc:7
#1  0x0000000000400656 in main () at target.cc:12
#2  0x00007ffff72d2ead in __libc_start_main (main=, argc=, ubp_av=, init=, fini=, rtld_fini=, stack_end=0x7fffffffe128) at libc-start.c:228
#3  0x0000000000400539 in _start ()
$1 = 0x7ffff763aee8

Get output of a command as a Python string

The above example only executes normal GDB commands. Let's get the output as a Python string. It can be achived by passing True to to_string parameter of get.execute() function. Python is also good at string processing, so you can easily extract and display specific strings in a formatted format.

The following exmaple shows the frame number and the last word from the stacktrace.
$ cat show-bt-and-format.py 
gdb.execute('b getval')
gdb.execute('run')
bt = gdb.execute('bt', to_string=True)
for line in bt.split('\n'):
  words = line.split(' ')
  print '%s %s' % (words[0], words[-1])
$ gdb -q -x show-bt-and-format.py  target
Reading symbols from /home/foo/target...done.
Breakpoint 1 at 0x400627: file target.cc, line 7.

Breakpoint 1, getval (div=5) at target.cc:7
7               return time(NULL) / div;
#0 target.cc:7
#1 target.cc:12
#2 libc-start.c:228
#3 ()

Show a memory map of the process being attached by GDB

You can show a memory map of a program being attached by info proc map. The following illustrates an example with 'cat' command.

'cat' command w/o arguments continue to wait for standard input. To operate GDB in that case, CTRL + C is typed in the following.

$ gdb /bin/cat
[skip]
(gdb) run
Starting program: /bin/cat 
^C <= Interrupt by typing CTRL + C
Program received signal SIGINT, Interrupt.
0x00007ffff7afe6a0 in __read_nocancel () at ../sysdeps/unix/syscall-template.S:81
81      ../sysdeps/unix/syscall-template.S: No such file or directory.
(gdb) info proc map
process 31692
Mapped address spaces:

          Start Addr           End Addr       Size     Offset objfile
            0x400000           0x40b000     0xb000        0x0 /bin/cat
            0x60a000           0x60b000     0x1000     0xa000 /bin/cat
            0x60b000           0x60c000     0x1000     0xb000 /bin/cat
            0x60c000           0x62d000    0x21000        0x0 [heap]
      0x7ffff7a12000     0x7ffff7bcf000   0x1bd000        0x0 /lib/x86_64-linux-gnu/libc-2.17.so
      0x7ffff7bcf000     0x7ffff7dcf000   0x200000   0x1bd000 /lib/x86_64-linux-gnu/libc-2.17.so
      0x7ffff7dcf000     0x7ffff7dd3000     0x4000   0x1bd000 /lib/x86_64-linux-gnu/libc-2.17.so
      0x7ffff7dd3000     0x7ffff7dd5000     0x2000   0x1c1000 /lib/x86_64-linux-gnu/libc-2.17.so
      0x7ffff7dd5000     0x7ffff7dda000     0x5000        0x0 
      0x7ffff7dda000     0x7ffff7dfd000    0x23000        0x0 /lib/x86_64-linux-gnu/ld-2.17.so
      0x7ffff7fcc000     0x7ffff7fcf000     0x3000        0x0 
      0x7ffff7ff8000     0x7ffff7ffa000     0x2000        0x0 
      0x7ffff7ffa000     0x7ffff7ffc000     0x2000        0x0 [vdso]
      0x7ffff7ffc000     0x7ffff7ffd000     0x1000    0x22000 /lib/x86_64-linux-gnu/ld-2.17.so
      0x7ffff7ffd000     0x7ffff7fff000     0x2000    0x23000 /lib/x86_64-linux-gnu/ld-2.17.so
      0x7ffffffde000     0x7ffffffff000    0x21000        0x0 [stack]
  0xffffffffff600000 0xffffffffff601000     0x1000        0x0 [vsyscall]
There is a similar command info shared. This only shows mapped shared libraries. The column 'Syms Read' indicates whethere the debug symbols has been read.
(gdb) info shared
From                To                  Syms Read   Shared Object Library
0x00007ffff7ddaaa0  0x00007ffff7df5439  Yes         /lib64/ld-linux-x86-64.so.2
0x00007ffff7a313c0  0x00007ffff7b7c39f  Yes         /lib/x86_64-linux-gnu/libc.so.6