Debugging Python with GDB

Last week, in the wonderful what did I learn today series, I’ve added Python debugging with GDB to my problem solving arsenal thank to Greg being back from a well deserved vacation.

Gdb is definitely not the tool I would have used to debug an interpreted language like Python, but it has a few great bindings that makes it perfect to follow the Python source inside a running process.

To do this, you need a root access to the machine you’ll use as gdb uses ptrace(2) to attach the process. If you can’t have root access, ask for temporary access using sudo(8).

The first thing to do is to ensure you have both Gdb and Python debugging symbols installed.

$ sudo apt-get install gdb python-dbg

Now, run the Python process you want to play with. To make it more simple, I’ve written a very simple one here that feels 3 local variables with some user input.

input_var = raw_input("Enter something: ")
print ("you entered " + input_var)
input_var2 = raw_input("Enter something else: ")
print ("you entered " + input_var2) 
input_var3 = raw_input("Final question: ")
print ("you entered " + input_var3)

Add the following to your homedir .gdbinit file:

$ echo 'add-auto-load-safe-path /usr/lib/debug/usr/bin/python2.7-gdb.py' >> ~/.gdbinit

Now, run the small Python script:

$ python test.py
Enter something: 

You’re ready to debug.

sudo gdb python -p PID
Attaching to program: /usr/bin/python, process 28943
Reading symbols from /lib/x86_64-linux-gnu/libpthread.so.0...(no debugging symbols found)...done.
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
Loaded symbols for /lib/x86_64-linux-gnu/libpthread.so.0
Reading symbols from /lib/x86_64-linux-gnu/libc.so.6...(no debugging symbols found)...done.
Loaded symbols for /lib/x86_64-linux-gnu/libc.so.6
Reading symbols from /lib/x86_64-linux-gnu/libdl.so.2...(no debugging symbols found)...done.
Loaded symbols for /lib/x86_64-linux-gnu/libdl.so.2
Reading symbols from /lib/x86_64-linux-gnu/libutil.so.1...(no debugging symbols found)...done.
Loaded symbols for /lib/x86_64-linux-gnu/libutil.so.1
Reading symbols from /lib/x86_64-linux-gnu/libz.so.1...(no debugging symbols found)...done.
Loaded symbols for /lib/x86_64-linux-gnu/libz.so.1
Reading symbols from /lib/x86_64-linux-gnu/libm.so.6...(no debugging symbols found)...done.
Loaded symbols for /lib/x86_64-linux-gnu/libm.so.6
Reading symbols from /lib64/ld-linux-x86-64.so.2...(no debugging symbols found)...done.
Loaded symbols for /lib64/ld-linux-x86-64.so.2
0x00007f60a6c35350 in read () from /lib/x86_64-linux-gnu/libc.so.6

Use the py-list command to display the current running code:

(gdb) py-list
  >1    input_var = input("Enter something: ")
   2    print ("you entered " + input_var)
   3    input_var2 = input("Enter something else: ")
   4    print ("you entered " + input_var2)
   5    input_var3 = input("Final question: ")
   6    print ("you entered " + input_var3)

The > shows the current line you’re running. Go back to your script and type something, enter, then switch back to gdb.

(gdb) n
Single stepping until exit from function read,
which has no line number information.
0x00007f7fb40c2120 in _IO_file_underflow () from /lib/x86_64-linux-gnu/libc.so.6

n tells gdb to run the code step by step. Let’s check where we are using py-list.

(gdb) py-list
   1    input_var = raw_input("Enter something: ")
   2    print ("you entered " + input_var)
  >3    input_var2 = raw_input("Enter something else: ")
   4    print ("you entered " + input_var2)
   5    input_var3 = raw_input("Final question: ")
   6    print ("you entered " + input_var3)

Since you’ve assigned a value to the global variable input_var, it would be interesting to check its value.

(gdb) py-print input_var
global 'input_var' = 'coucou'

That’s all for today. There’s probably more to do with GDB but so far it’s been pretty useful to me to understand lots of problems running strace did not enlighten.

Perry the Platypus wants you to subscribe now! Even if you don't visit my site on a regular basis, you can get the latest posts delivered to you for free via Email: