Sunday, 29 January 2012

Catching exceptions in GDB

There's a problem running gdb from GNAT GPL 2011 (which works fine with programs compiled with GNAT GPL 2011) on programs compiled with GCC 4.6 on Max OS X Lion and possibly earlier; you can't catch exceptions as you'd expect:

(gdb) break exception
Unable to insert catchpoint. Try to start the program first.
You can say break __gnat_debug_raise_exception, which is better than nothing, but doesn't - for example - allow you to break exception constraint_error.

I don't have a fix for this, but a similar problem is actually already on the GDB Bugzilla which, interestingly, was reported on i686-redhat-linux-gnu.

I thought I might get further by building my own gdb.

I've cloned the GDB git repository:

$ git clone git:// gdb-git

(the CVS checkout described here wouldn't configure), and built by

$ mkdir gdb-build
$ cd gdb-build
$ ../gdb-git/configure CC="gcc -g -O0"

I redefined CC because normally GDB builds with -g -O2 and inlines some of the code I needed to debug while working out what's going on (using the system gdb to debug the gdb you just built is more than somewhat confusing!)

break exception doesn't work with this GDB:

(gdb) break exception
Function "exception" not defined.
Make breakpoint pending on future shared library load? (y or [n]) n

and catch exception fails like GNAT GPL 2011's gdb:

(gdb) catch exception
Unable to insert catchpoint. Try to start the program first.

It turns out that the failure mode of catch exception is that it looks for the symbol __gnat_debug_raise_exception in an Ada-specific way and fails to find it; but other references to the same symbol (such as break __gnat_debug_raise_exception) do work, and, after that, so does catch exception!

You can't put this into a .gdbinit file, because they get run before your executable is loaded. Instead, you could have a file ~/gdb.catch:

print __gnat_debug_raise_exception

after which you can say

$ gdb -x ~/gdb.catch foo

You could also set up an alias, alias adagdb='gdb -x ~/gdb.catch'.

An even simpler solution may be to invoke gdb with -readnow:

$ gdb -readnow foo

Edit 5.iii.16: add -readnow workround.

No comments:

Post a Comment