This is the mail archive of the gdb-patches@sourceware.cygnus.com mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

Generic g++ exception catch/throw support


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 &current_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 &current_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 () */
!         }
  
      }
  }
  

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]