This is the mail archive of the
gdb-patches@sourceware.cygnus.com
mailing list for the GDB project.
Generic g++ exception catch/throw support
- To: gdb-patches at sourceware dot cygnus dot com
- Subject: Generic g++ exception catch/throw support
- From: Daniel Berlin <dan at cgsoftware dot com>
- Date: Tue, 25 Jan 2000 10:39:37 -0800 (PST)
Using this patch, you can get generic g++ exception catch/throw support
(using catch catch and catch throw).
You need to add a handler to your target's -nat file that looks like this:
/*Use knowledge of how g++ exceptions work to properly determine if we are in a throw or catch*/
static struct exception_event_record current_ex;
struct exception_event_record *
beos_get_current_exception_event ()
{
struct symbol *currsym;
char *name;
CORE_ADDR start,end;
/*Unless you have a libgcc with full debugging info, it'll always be a partial function.
* This saves time and memory by only searching the partial symtabs.*/
if (!find_pc_partial_function(read_register(PC_REGNUM),&name,&start,&end))
{
return (struct exception_event_record *) NULL;
}
/*Throw helper is called by throw and rethrow, to do the actual throwing*/
if (STREQ(name,"throw_helper"))
{
CORE_ADDR thepc;
const int level=2; /* Throw Location->(__throw or __rethrow)->throw_helper*/
thepc=get_frame_pc(find_relative_frame(get_current_frame(),&level));
current_ex.kind=EX_EVENT_THROW;
current_ex.throw_sal=find_pc_line(thepc,1);
return ¤t_ex;
}
/*Start cp handler is called once we have found something to handle the exception,
* so we know we have caught it*/
else if (STREQ(name,"__start_cp_handler"))
{
CORE_ADDR thepc;
const int level=1;/* Catch location->(__start_cp_handler)*/
thepc=get_frame_pc(find_relative_frame(get_current_frame(),&level));
current_ex.kind=EX_EVENT_CATCH;
current_ex.catch_sal=find_pc_line(thepc,1);
return ¤t_ex;
}
return (struct exception_event_record *) NULL;
}
Change the name, obviously.
You should now see the catch and throw locations.
Note that i'm not memsetting the throw/catch location on catch/throw, so
that it'll print hte original throw location when you catch.
Obviously this breaks if you throw right after a catch, or catch two
different exceptions in a row (It'll display the wrong location for the
thing i haven't zero'd out. The catch location on catches, and the throw
location on throws, will always be correct)
This has been tested against all kinds of exception tests, and works
flawlessly.
--Dan
Index: breakpoint.c
===================================================================
RCS file: /cvs/gdb/gdb/gdb/breakpoint.c,v
retrieving revision 1.1.1.23
diff -c -3 -p -r1.1.1.23 breakpoint.c
*** breakpoint.c 2000/01/11 03:07:17 1.1.1.23
--- breakpoint.c 2000/01/25 18:33:25
*************** catch_exception_command_1 (ex_event, arg
*** 5856,5862 ****
{
char *cond_string = NULL;
struct symtab_and_line *sal = NULL;
!
ep_skip_leading_whitespace (&arg);
cond_string = ep_parse_optional_if_clause (&arg);
--- 5856,5862 ----
{
char *cond_string = NULL;
struct symtab_and_line *sal = NULL;
! struct symtabs_and_lines sals;
ep_skip_leading_whitespace (&arg);
cond_string = ep_parse_optional_if_clause (&arg);
*************** catch_exception_command_1 (ex_event, arg
*** 5882,5901 ****
}
else
{
! /* No callbacks from runtime system for exceptions.
Try GNU C++ exception breakpoints using labels in debug info. */
if (ex_event == EX_EVENT_CATCH)
! {
! handle_gnu_4_16_catch_command (arg, tempflag, from_tty);
! }
else if (ex_event == EX_EVENT_THROW)
! {
! /* Set a breakpoint on __raise_exception () */
- warning ("Unsupported with this platform/compiler combination.");
- warning ("Perhaps you can achieve the effect you want by setting");
- warning ("a breakpoint on __raise_exception().");
- }
}
}
--- 5882,5906 ----
}
else
{
! /* No callbacks from runtime system for exceptions.
Try GNU C++ exception breakpoints using labels in debug info. */
if (ex_event == EX_EVENT_CATCH)
! {
! char *hookname="__start_cp_handler";
! /* Set a breakpoint on the specified hook. */
! sals = decode_line_1 (&hookname, 1, (struct symtab *) NULL, 0, 0);
! create_exception_catchpoint(tempflag, cond_string, ex_event, (sals.sals));
! }
!
else if (ex_event == EX_EVENT_THROW)
! {
! char *hookname="throw_helper";
! /*Set a breakpoint on the specified hook. */
! sals=decode_line_1(&hookname,1,(struct symtab *)NULL,0,0);
! create_exception_catchpoint(tempflag,cond_string,ex_event,(sals.sals));
! /* Set a breakpoint on __raise_exception () */
! }
}
}