Fantaisies programatico-ludiques

gdb Python macros

This post aims to introduce a very useful tool to debug low-level issues in Python, how to enhance it and finally how to solve two annoying common problems.

1. Debugging Python with gdb

All the basics are there :

Tl;dr :

gdb -p $(pgrep -f your_running_python_program_name)

2. Installing the macros for Python

A set of GDB macros are distributed with Python that aid in debugging the Python process. (from:

One-liner to install those macros:

curl --silent >> ~/.gdbinit

There is a minor fix to the lineno macro to make:

sed -i 's/printf "%d", $__li/printf "%d", $__li + 1/' ~/.gdbinit

Usage example taken from the comments:

(gdb) pyo apyobjectptr
<module 'foobar' (built-in)>
refcounts: 1
address    : 84a7a2c
$1 = void
Quoted from: Python SVN Misc/.gdbinit

Some other useful macros: pystack, printframe, pylocals. List them all with: grep define ~/.gdbinit.

3. Persistent history & colored prompt

The following command will append some lines to your ~/.gdbinit configuration file in order to keep a persistent history between your gdb sessions, and to set a very useful colored prompt:

cat <<END >> ~/.gdbinit

# Custom configuration by USER=$USER
## Persistent history:
set history save
set history filename ~/.gdb_history
## Colored prompt:
set prompt \001\033[1;32m\002(gdb)\001\033[0m\002\040

All the credit for this trick goes to Peter Jay Salzman. Here is also a more complete improved .gdbinit :

4. Solving: 'ptrace: Operation not permitted'

DO NOT SET THE SUID/SGID BIT : sudo chmod +s /usr/bin/gdb

As explained in the comments (thanks to Romain Geissler), this solution I initially recommended actually creates a security vulnerability.

A better solution looks to be :

echo 0 > /proc/sys/kernel/yama/ptrace_scope # to execute as root

Or setting kernel.yama.ptrace_scope = 0 in /etc/sysctl.d/10-ptrace.conf.

5. Solving: 'No symbol "co" in current context'

This one is trickier. It's a known issue described in The recommended solution is to Recompile python with make CFLAGS=-g -fno-inline -fno-strict-aliasing (the alternative patch did not work for me).

Yeah, I know, SIGH...

But it's in fact not so difficult to built a stand-alone python interpreter:

dbg_py_v=2.7.8; dbg_py=Python-$dbg_py_v
mkdir /opt; cd /opt
curl -L$dbg_py_v/$dbg_py.tar.xz | tar xJvf -
cd $dbg_py
./configure --prefix=/usr/local --enable-unicode=ucs4 --disable-shared LDFLAGS="-Wl,-rpath /usr/local/lib"
make -j3 "CFLAGS=-g -fno-inline -fno-strict-aliasing"

Then simply:

export PYTHONPATH=... # can be extracted from the original script with print('\n'.join(sys.path))
/opt/$dbg_py/python your_python_program

And no more "undefined symbol" error message in gdb !

EDIT: Actually, if your gdb version has been compiled with python support (gdb --batch --quiet -ex 'show configuration' | grep with-python), no need to download any .gdbinit file ! You can replace all those macros definition by this single line in your .gdbinit (after manually replacing the $dbg_py variable) :

add-auto-load-safe-path /opt/$dbg_py/

You now have access to all the following commands:

  • py-bt
  • py-list
  • py-down / py-up
  • py-locals
  • py-print

On the other hand, the latest version of the gdbinit file on the new Mercurial repository doesn't seem to work: I get a 'No symbol "_PyUnicode_AsString" in current context.' error message.

EDIT (2016/04/15): a more recent article on the subject :

The following commands taken from this article helped me once:

yum install python33-python-debuginfo glibc-debuginfo
# from base-debuginfo repository - can also be installed with: debuginfo-install ...

In gdb :

source /usr/lib/debug/opt/rh/python33/root/usr/lib64/