Debug-stepping through GTK+ code (Debian/Ubuntu)
Here is an easy way to setup GDB to step through the GTK+ source code if you're using the Debian (or Ubuntu) -dbg packages.
First thing to do, if you haven't already done it, is to install the relevant debug packages. `gnome-dbg` is a metapackage which depends on a few other GNOME debug packages. Install it if you have enough disk space. If you're like me and can't spare the GBs then install only the necessary dependencies. In my case: `gnome-panel-dbg` `libglib2.0-0-dbg` `libgtk2.0-0-dbg`.
The -dbg packages put a tree of unstripped shared libraries in /usr/lib/debug. Unstripped objects contain symbol definitions (e.g. function names and their addresses) and debugging information (i.e. a mapping from instruction addresses to source code line numbers).
At this point you already have some useful information. When you debug your app in GDB you will notice that GDB reads symbols from the objects in /usr/lib/debug corresponding to the ones in /usr/lib. So when you look at the backtrace, function names will appear instead of something like this: #3 0x0f09ad50 in ?? () from /usr/lib/libgobject-2.0.so.0. However it would be nice to be able to trace through the source code.
The source code corresponding to a library is easy enough to get if you're using Debian. You just need somewhere to put it. I have mine in ~/dev/pkg. So:
$ cd ~/dev/pkg $ apt-get source gnome-panel-dbg libglib2.0-0-dbg libgtk2.0-0-dbg
If you try going up your backtrace in GDB and stepping through the GTK+ code you will see no code and a message like this:
gtk_widget_event_internal (widget=0x100ca420, event=0x10190ee8) at /build/buildd/gtk+2.0-2.12.3/gtk/gtkwidget.c:4677 4677 /build/buildd/gtk+2.0-2.12.3/gtk/gtkwidget.c: No such file or directory. in /build/buildd/gtk+2.0-2.12.3/gtk/gtkwidget.c
The directory /build/buildd is the directory from which your GTK+ was built, when it was built on some other unknown machine. This will vary depending on the distribution (Debian or Ubuntu), the architecture, the package, and whoever happens to be the package maintainer. If you built the GTK+ package yourself it would be different. Sometimes the filename referred to is not absolute, e.g. this is the case for libpanel-applet.
Absolute filenames like `/build/buildd` or `/scratch/build-area`
In this case, the easiest way is to create a source path substitution rule like this:
set substitute-path /build/buildd __/home/rodney/dev/pkg__
Change /build/buildd to whatever directory the debug symbols point to.
Change the underlined path to the place where you ran the apt-get source command.
No path in filename
If the message looks like this:
#5 0x00007f0521248624 in panel_applet_factory_main_closure ( iid=0x404b74 "OAFIID:PanelVisApplet_Factory", applet_type=<value optimized out>, closure=<value optimized out>) at panel-applet.c:1754 1754 panel-applet.c: No such file or directory. in panel-applet.c
i.e. gdb is looking for a file in the current directory, then find where the sources are.
$ find ~/dev/pkg -name panel-applet.c -printf '%h\n' /home/rodney/dev/pkg/gnome-panel-2.24.2/libpanel-applet
And then use the dir command in gdb.
Put these commands in your `~/.gdbinit` and you will never have to think about it again... until someone upgrades the library.
When the library packages are upgraded, the paths with become invalid, because they have the version in them. In this case, you will need to re-run the apt-get source command to retrieve the source code which matches your library version, then update your ~/.gdbinit. Alternatively, you could keep the old source code and add extra substitution rules to point GDB to the old code. However I don't recommend this practice because the debugger will appear to act strange if the source code is too different and the line numbers don't match up. A nasty surprise like that is the last thing you need when you're up at 2AM debugging something.
Originally posted on 11/1/2008 at http://rodney.id.au/dev/gnome/debug-stepping-through-gtk-code.