www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Unhandled exceptions on Linux

reply =?UTF-8?B?U3TDqXBoYW4gS29jaGVu?= <stephan kochen.nl> writes:
Hi all,

Windows users seem to get spoiled with Ddbg and all that. I haven't
checked it out personally, but I certainly wanted some better debugging
tools in Linux.

I figured out how to break in GDB on unhandled exceptions, and leave the
stack intact to get a backtrace. I wanted to do this with a downloaded
binary version of DMD and Phobos, but I may need some help with GDB
scripting.

Basically, my GDB script right now looks as follows, but this will only
work in my specific situation (read on):

start
set no_catch_exceptions=1
break *0x08069558

'no_catch_exceptions' is a global boolean variable in Phobos that can be
used to disable the default unhandled exception handling. (This default
simply prints Exception.toString().) You can find the code for this in
'phobos/internal/dmain2.d'.

The 'start' command to GDB is required to get to the global.

Normally, Phobos wraps your D main() function with a try-catch that
catches any exception. By disabling this, the stack unwinding that
happens when an exception is thrown falls all the way through. The
result is that an unhandled exception is literally left unhandled, and
your program would continue running. You can see this in the '_d_throw'
method in 'phobos/internal/deh2.d'.

This situation is then easily caught by setting a breakpoint at the end
of '_d_throw'. The address I use in the 'break' command above, however,
will only work in my specific case. I'm guessing for a static library
this address will change when the application changes, or the library
changes.

To get to that address, all I've done now is the following in GDB:

disassemble '_d_throw 4'

And then just hand-pick the address at the very end.

I'd like to do this programmatically in a GDB script, though. Is anyone
here more familiar with GDB to help me out?

Thanks in advance,
-- Stéphan
Aug 21 2007
parent reply Nathan Reed <nathaniel.reed gmail.com> writes:
Stéphan Kochen wrote:
 To get to that address, all I've done now is the following in GDB:
 
 disassemble '_d_throw 4'
 
 And then just hand-pick the address at the very end.

I'm not extremely familiar with GDB scripting either, but presumably the size of the routine won't change very much, so would it let you write the address as "_d_throw 4 + n" where n is an integer constant? Disassembling libphobos2.a shows the address of the last instruction as offset 0x214 from the beginning of the function. Thanks, Nathan Reed
Aug 21 2007
parent =?UTF-8?B?U3TDqXBoYW4gS29jaGVu?= <stephan kochen.nl> writes:
Nathan Reed schreef:
 I'm not extremely familiar with GDB scripting either, but presumably the size
of the routine won't change very much, so would it let you write the address as
"_d_throw 4 + n" where n is an integer constant?  Disassembling libphobos2.a
shows the address of the last instruction as offset 0x214 from the beginning of
the function.

That does help a bit, yes: (gdb) print '_d_throw 4' + 0x214 $1 = (<text variable, no debug info> *) 0x8069558 <_d_throw 4+532> (gdb) break *$ Breakpoint 2 at 0x8069558 Thanks! More suggestions welcome, of course. :) -- Stéphan
Aug 21 2007