Gdb support for exceptions (Re: using backtrace() in exception throwing?)
Tom Tromey
tromey at redhat.com
Wed Feb 27 13:28:54 PST 2013
>>>>> "Tom" == Tom Tromey <tromey at redhat.com> writes:
Tom> The various low-level exception-related functions, like __cxa_throw,
Tom> treat the exception object as a "void *". However, the value of this
Tom> seems to change depending on the "throw" point. It's clear that this
Tom> can't always be the argument to throw, due to scalar and object throws.
Tom> So I wonder what exactly it refers to. I'll have to dig a bit deeper to
Tom> see how all this code really works.
[...]
Tom> It seems like it would be nice if gdb exposed some kind of convenience
Tom> variable so that "catch catch" and "catch throw" could be conditional on
Tom> the thrown object without needing the libstdc++ debuginfo.
[...]
Tom> This may require some libstdc++ change, perhaps a probe point.
I did some more digging here and wrote a few patches.
When throwing an exception, the compiler arranges to allocate an
internal exception object with enough extra space for the exception
passed to "throw". Then it copy-constructs from the thrown object into
this space and it records the object's type_info into the internal
exception object.
I added some SDT probes to libstdc++ to expose this information more
nicely (there's really no good way to do it in all cases right now, even
with debuginfo installed, as a couple of the probes are mid-function).
So now I can:
(gdb) catch throw
Catchpoint 1 (throw)
(gdb) r
Starting program: /home/tromey/Space/SecondArcher/build/gdb/testsuite/gdb.cp/exception
[... loads of gunk ...]
Catchpoint 1 (exception thrown), __cxxabiv1::__cxa_throw (obj=0x601090,
tinfo=0x600e60 <typeinfo for int@@CXXABI_1.3>, dest=0x0)
at ../../../../gcc/libstdc++-v3/libsupc++/eh_throw.cc:63
63 PROBE2 (throw, obj, tinfo);
(gdb) p $_exception
$1 = 13
Note that the exception variable automatically has the right type:
(gdb) up
#1 0x0000000000400873 in foo (i=20)
at ../../../archer/gdb/testsuite/gdb.cp/exception.cc:28
28 throw (int) 13;
So, cool.
The bad news is, since this requires a libstdc++ patch, even once I get
everything tidied up and approved and committed, it is going to be a
while before you can use it, unless you're willing to build your own gcc
and gdb.
Tom> If we had the convenience variable mentioned above, and if LibreOffice
Tom> has a relatively simple "exception identity" measure (e.g., if you only
Tom> throw pointers, you can just compare them with ==), then it could
Tom> perhaps be done by: break at the losing catch, make a conditional "catch
Tom> throw", then re-run.
This does turn out to be a tricky bit.
gdb generally mimics the source language, so things like:
cond 5 $_exception == 23
... will fail if some exception thrown is not actually comparable to 23.
I'm investigating some options here. Maybe a more-magical "==="
operator, or maybe a Python convenience function like:
cond 5 $_dwim_equals ($_exception, 23)
I also implemented a way to filter exception catches by name:
catch catch [REGEXP]
catch throw [REGEXP]
catch rethrow [REGEXP]
That will help the above problem a bit, you can do:
catch catch int if $_exception == 23
I think all this should help with the problems that started this thread.
Insight, advice, ideas -- send them my way.
thanks,
Tom
More information about the LibreOffice
mailing list