Tuesday, 23 March 2010

Using glib.py and gobject.py GDB scripts

Some time ago, Alexander Larson blogged about using gdb python macros when debugging Glib and GObject projects. I've wanted to try those for ages, so I spent part of the week-end looking at what you could do with the new python enabled GDB, result: quite a lot of neat stuff!

Let's start by making the script that now comes with glib work on stock gdb 7.0 and 7.1 (ie not the archer branch that contains more of the python work). If those two scripts don't work for you yet (because your distribution is not packaging them, or is packaging a stock gdb 7.0. 7.1), here are a few hints you can follow:
  • glib's GDB macros rely on GDB's auto-load feature, ie, every time GDB load a library your program uses, it'll look for a corresponding python script to execute:
open("/lib/libglib-2.0.so.0.2200.4-gdb.py", O_RDONLY)
open("/usr/lib/debug/lib/libglib-2.0.so.0.2200.4-gdb.py", O_RDONLY)
open("/usr/share/gdb/auto-load/lib/libglib-2.0.so.0.2200.4-gdb.py", O_RDONLY)
Some distributions have decided not to ship glib's and gobject's auto-load helpers, if you are in that case, you'd need to load gobject.py and glib.py by hand. For that purpose I've added a small python command in my ~/.gdbinit:
import os.path
import sys
import gdb

# Update module path.
dir = os.path.join(os.path.expanduser("~"), ".gdb")
if not dir in sys.path:
    sys.path.insert(0, dir)

class RegisterCommand (gdb.Command):
"""Register GLib and GObject modules"""

    def __init__ (self):
        super (RegisterCommand, self).__init__ ("gregister",

    def invoke (self, arg, from_tty):
        objects = gdb.objfiles ()
        for object in objects:
            if object.filename.find ("libglib-2.0.so.") != -1:
                from glib import register
                register (object)
            elif object.filename.find ("libgobject-2.0.so.") != -1:
                from gobject import register
                register (object)

RegisterCommand ()
What I do is put glib.py and gobject.py in a ~/.gdb directory and don't forget to call gregister inside GDB (once gdb has loaded glib and gobject)
  • The scripts that are inside glib's repository were written with the archer branch of gdb (which bring all the python stuff). Unfortunately stock GDB (7.0 and 7.1) does not have everything the archer gdb has. I have a couple of patches to fix that in the queue. Meanwhile you can grab them in my survival kit repository. This will disable the back trace filters as they are still not in stock GDB.

You're all set! it's time to enjoy pretty printing and gforeach. Hopefully people will join the fun at some point and add more GDB python macro goodness both inside glib and in other projects (for instance a ClutterActor could print its name).
int main (int argc, char **argv)
glist = g_list_append (glist, "first");
glist = g_list_append (glist, "second");

return breeeaaak_oooon_meeeee ();
(gdb) b breeeaaak_oooon_meeeee
Breakpoint 1 at 0x80484b7: file glib.c, line 9.
(gdb) r
Starting program: /home/damien/src/test-gdb/glib
Breakpoint 1, breeeaaak_oooon_meeeee () at glib.c:9
9        return 0;
(gdb) gregister
(gdb) gforeach s in glistp: print ((char *)$s)
No symbol "glistp" in current context.
(gdb) gforeach s in glist: print ((char *)$s)
$2 = 0x80485d0 "first"
$3 = 0x80485d6 "second"

No comments:

Post a Comment