WatchPoint

Image link

GDB Python Integration: Debugging with Python in GDB

In this episode of gdbWatchPoint we’re going to look at using the GDB python integration. It’s a big topic worthy of its own dedicated screencast series and we’re going to a few episodes.

GDB has a really tight integration with python. You can do all kinds of cool things to make really thorny debug problems tractable; plus there’s lots you can do to customize GDB to your particular project.

We’re going to use the simple example program that we’ve used previous on gdbWatchPoint:

include <stdio.h>
int
main(void)
{
  printf("Hello, world!\n");
  printf("That is all, goodbye.\n");
  return 0;
}

Compile this with gcc -g hello.c and launch GDB with gdb o.out.

 

GDB Python – The inner workings

Let’s start by invoking the python interpreter in the simplest way we can. Typing python invokes the interpreter, the python print() function is called and executed when I type end.

(gdb) python 
> print('Hello world')
> end
Hello world

The python code isn’t passed to another python process but is run inside the GDB process. We can see this for ourselves using the os.getpid() method:

(gdb) python
> import os
> print('I am pid ()'.format(os.getpid()))
> end
I am pid 4286

I can also shell out from GDB using the shell command which I can use to prove that python is running inside the GDB process:

GDB integrated python code

This is good to know because it means that python is truly integrated.

New call-to-action

 

GDB Python is long-lived

The python process is long lived within GDB which means variables and methods will persist. For example, if I do:

(gdb) python foo = 42

and then:

(gdb) python print(foo)

we can see that this returns:

42

Which means foo is still there as 42, so the python inside GDB is stateful allowing you to build up the environment over time.

 

Python GDB integration

In order to use the python GDB integration, you first need to import the gdb module which gives you lots of cool stuff:

(gdb) python import gdb

The simplest thing this gives you is the .execute method which feeds a command straight into GDB:

python gdb.execute

In TUI mode, we can use the .execute command to create a breakpoint and see it indicated on the left of the source code:

 

python gdb.execute hello world

This shows what can be done, but it isn’t really very interesting. More interesting is when we use the GDB integration properly, which we can do be creating an instance of gdb.Breakpoint:

 

gdb.execute hello c:7

Now I have the gdb.Breakpoint object, I can start to manipulate and interrogate it. For example, to see if the breakpoint is enabled I can run:

(gdb) python print(bp.enabled)
True

Which shows me the breakpoint is enabled. I can change this with:

(gdb) python bp.enabled = False

And so you can begin to imagine what’s possible with the GDB integration with Python.

 

New call-to-action

 

Help for python gdb integration

The python inbuilt help for gdb is useful and pretty thorough. For example, to get the help on the bp object which we created above, run:

(gdb) python help(bp)

That tells me all about the Breakpoint class:

 

gdb watchpoint

You can see that this is how tight the integration is. Pretty much anything that can be done at the GDB command line can be done with a breakpoint from Python. You can attach commands to a breakpoint, make it conditional, ignore a certain number of hits, make the breakpoint specific to a thread or process, and all of the things you can do from the command line.

The same is true of most other things in GDB; if you can do it from the GDB command line, you can do it from python. You can see this in the help documentation for the GDB module:

(gdb) python help(gdb)

Browsing this shows everything which you can do. For example, the higlighted lines are things about the program you’re debugging – your inferior – which allows you to explore the program, blocks, lines and so forth.

 

You can see access to events such as thread StopEvents, which might come from a BreakpointEvent or SignalEvent.

One thing we’ll cover in a future episode is how you can trigger functions to run when certain events occur.

From all of this, you can pull out of the inferior a lot of the information you need for debugging and the ability to drive GDB. You can create pretty printers and custom commands so you can customize GDB to work better your particular project or in your organization.

Don’t miss my next C++ debugging tutorial: sign up to my WatchPoint mailing list below.
Get tutorials straight to your inbox

Become a GDB Power User. Get Greg’s debugging tips directly in your inbox every 2 weeks.

Want GDB pro tips directly in your inbox?

Share this tutorial