[rfc breakpoint] Catch exceptions

Daniel Jacobowitz drow@mvista.com
Tue Mar 25 03:01:00 GMT 2003


I'm just looking for feedback on this patch.  It's mostly complete except
for some mass re-indenting that some of the changes would require; I'm not
entirely happy with the design yet though, so I'm looking for comments.

The feature being implemented here is "catch catch" and "catch throw".  This
patch just does gcc v3; gcc v2.95 is easy to add afterwards, and I also have
a patch to remove the ancient GNU support for this feature for some 1.x g++
versions (or maybe early 2.x?).  HP, as usual, supports this in a completely
different way.

The basic idea is that these "catchpoints" are just normal breakpoints and
should be handled as such.  But we'd like to print them a little
differently, for clarity.

Here's the interesting bit, from struct breakpoint:
+    enum print_stop_action (*print) (struct breakpoint *);
+
+    void (*print_one) (struct breakpoint *, CORE_ADDR *);
+
+    void (*print_mention) (struct breakpoint *);

i.e. it adds function pointers to the breakpoint to describe the action to
take.  Logical next steps include a function to determine whether to stop
(for catch throw TYPE) and maybe even a function to take action when hit (to
simplify longjmp and step_resume breakpoints, etc. - breakpoint.c could be
simplified by this mechanism long-term).

[Why three subtly different print functions?  Because there were three
places I needed a hook and they were all different.  This sucks.  At least
two of them can be condensed... I think... eventually.  I'm not interested
in doing that level of cleanup right now, particularly.]

Comments?  If no one has any, I'll look to commit this (with reformatting)
in a while.  Maybe a week or so.

-- 
Daniel Jacobowitz
MontaVista Software                         Debian GNU/Linux Developer

Index: breakpoint.c
===================================================================
RCS file: /big/fsf/rsync/src-cvs/src/gdb/breakpoint.c,v
retrieving revision 1.114
diff -u -p -r1.114 breakpoint.c
--- breakpoint.c	11 Mar 2003 19:07:01 -0000	1.114
+++ breakpoint.c	25 Mar 2003 02:49:23 -0000
@@ -2017,6 +2013,9 @@ print_it_typical (bpstat bs)
   if (bs->breakpoint_at == NULL)
     return PRINT_UNKNOWN;
 
+  if (bs->breakpoint_at->print != NULL)
+    return (*bs->breakpoint_at->print) (bs->breakpoint_at);
+
   switch (bs->breakpoint_at->type)
     {
     case bp_breakpoint:
@@ -3272,7 +3271,10 @@ print_one_breakpoint (struct breakpoint 
       else
 	strcat (wrap_indent, "                   ");
     }
-  switch (b->type)
+
+  if (b->print_one != NULL)
+    (*b->print_one) (b, last_addr);
+  else switch (b->type)
     {
     case bp_none:
       internal_error (__FILE__, __LINE__,
@@ -4420,7 +4423,9 @@ mention (struct breakpoint *b)
     create_breakpoint_hook (b);
   breakpoint_create_event (b->number);
 
-  switch (b->type)
+  if (b->print_mention != NULL)
+    (*b->print_mention) (b);
+  else switch (b->type)
     {
     case bp_none:
       printf_filtered ("(apparently deleted?) Eventpoint %d: ", b->number);
@@ -6192,6 +6016,84 @@ create_exception_catchpoint (int tempfla
   mention (b);
 }
 
+static enum print_stop_action
+print_exception_catchpoint (struct breakpoint *b)
+{
+  annotate_catchpoint (b->number);
+
+  if (strstr (b->addr_string, "throw") != NULL)
+    printf_filtered ("\nCatchpoint %d (exception thrown)\n",
+		     b->number);
+  else
+    printf_filtered ("\nCatchpoint %d (exception caught)\n",
+		     b->number);
+
+  return PRINT_SRC_AND_LOC;
+}
+
+static void
+print_one_exception_catchpoint (struct breakpoint *b, CORE_ADDR *last_addr)
+{
+  if (addressprint)
+    {
+      annotate_field (4);
+      ui_out_field_core_addr (uiout, "addr", b->address);
+    }
+  annotate_field (5);
+  *last_addr = b->address;
+  if (strstr (b->addr_string, "throw") != NULL)
+    ui_out_field_string (uiout, "what", "exception throw");
+  else
+    ui_out_field_string (uiout, "what", "exception catch");
+}
+
+static void
+print_mention_exception_catchpoint (struct breakpoint *b)
+{
+  if (strstr (b->addr_string, "throw") != NULL)
+    printf_filtered ("Catchpoint %d (throw)", b->number);
+  else
+    printf_filtered ("Catchpoint %d (catch)", b->number);
+}
+
+static int
+handle_gnu_v3_exceptions (int tempflag, char *cond_string,
+			  enum exception_event_kind ex_event, int from_tty)
+{
+  struct minimal_symbol *trigger_func;
+  const char *trigger_func_name;
+  struct symtab_and_line sal;
+  struct breakpoint *b;
+
+  if (ex_event == EX_EVENT_CATCH)
+    trigger_func_name = "__cxa_begin_catch";
+  else
+    trigger_func_name = "__cxa_throw";
+
+  trigger_func = lookup_minimal_symbol (trigger_func_name, NULL, NULL);
+  if (trigger_func == 0)
+    return 0;
+  sal = find_msymbol_start_sal (trigger_func, 1);
+
+  b = set_raw_breakpoint (sal, bp_breakpoint);
+  set_breakpoint_count (breakpoint_count + 1);
+  b->number = breakpoint_count;
+  b->cond = NULL;
+  b->cond_string = (cond_string == NULL) ? 
+    NULL : savestring (cond_string, strlen (cond_string));
+  b->thread = -1;
+  b->addr_string = xstrdup (trigger_func_name);
+  b->enable_state = bp_enabled;
+  b->disposition = tempflag ? disp_del : disp_donttouch;
+  mention (b);
+  b->ep_type = ep_gnuv3;
+
+  b->print = print_exception_catchpoint;
+  b->print_one = print_one_exception_catchpoint;
+  b->print_mention = print_mention_exception_catchpoint;
+  return 1;
+}
+
 /* Deal with "catch catch" and "catch throw" commands */
 
 static void
@@ -6212,6 +6114,9 @@ catch_exception_command_1 (enum exceptio
       (ex_event != EX_EVENT_CATCH))
     error ("Unsupported or unknown exception event; cannot catch it");
 
+  if (handle_gnu_v3_exceptions (tempflag, cond_string, ex_event, from_tty))
+    return;
+
   /* See if we can find a callback routine */
   sal = target_enable_exception_callback (ex_event, 1);
 
Index: breakpoint.h
===================================================================
RCS file: /big/fsf/rsync/src-cvs/src/gdb/breakpoint.h,v
retrieving revision 1.19
diff -u -p -r1.19 breakpoint.h
--- breakpoint.h	20 Feb 2003 00:01:05 -0000	1.19
+++ breakpoint.h	25 Mar 2003 02:46:57 -0000
@@ -305,6 +305,14 @@ struct breakpoint
        triggered.  */
     char *exec_pathname;
 
+    enum {ep_normal, ep_gnuv2, ep_gnuv3} ep_type;
+
+    enum print_stop_action (*print) (struct breakpoint *);
+
+    void (*print_one) (struct breakpoint *, CORE_ADDR *);
+
+    void (*print_mention) (struct breakpoint *);
+
     asection *section;
   };
 
Index: linespec.c
===================================================================
RCS file: /big/fsf/rsync/src-cvs/src/gdb/linespec.c,v
retrieving revision 1.45
diff -u -p -r1.45 linespec.c
--- linespec.c	3 Mar 2003 17:20:24 -0000	1.45
+++ linespec.c	17 Mar 2003 17:06:34 -0000
@@ -1543,14 +1543,7 @@ minsym_found (int funfirstline, struct m
 
   values.sals = (struct symtab_and_line *)
     xmalloc (sizeof (struct symtab_and_line));
-  values.sals[0] = find_pc_sect_line (SYMBOL_VALUE_ADDRESS (msymbol),
-				      (struct sec *) 0, 0);
-  values.sals[0].section = SYMBOL_BFD_SECTION (msymbol);
-  if (funfirstline)
-    {
-      values.sals[0].pc += FUNCTION_START_OFFSET;
-      values.sals[0].pc = SKIP_PROLOGUE (values.sals[0].pc);
-    }
+  values.sals[0] = find_msymbol_start_sal (msymbol, funfirstline);
   values.nelts = 1;
   return values;
 }
Index: symtab.c
===================================================================
RCS file: /big/fsf/rsync/src-cvs/src/gdb/symtab.c,v
retrieving revision 1.99
diff -u -p -r1.99 symtab.c
--- symtab.c	4 Mar 2003 17:06:21 -0000	1.99
+++ symtab.c	17 Mar 2003 17:08:01 -0000
@@ -2462,6 +2462,27 @@ find_function_start_sal (struct symbol *
   return sal;
 }
 
+/* Given a minimal symbol MSYMBOL, build a corresponding struct
+   symtabs_and_lines.
+   If the argument FUNFIRSTLINE is nonzero, we want the first line
+   of real code inside the function, so skip the prologue.  */
+
+struct symtab_and_line
+find_msymbol_start_sal (struct minimal_symbol *msymbol, int funfirstline)
+{
+  struct symtab_and_line sal;
+
+  sal = find_pc_sect_line (SYMBOL_VALUE_ADDRESS (msymbol),
+			   (struct sec *) 0, 0);
+  sal.section = SYMBOL_BFD_SECTION (msymbol);
+  if (funfirstline)
+    {
+      sal.pc += FUNCTION_START_OFFSET;
+      sal.pc = SKIP_PROLOGUE (sal.pc);
+    }
+  return sal;
+}
+
 /* If P is of the form "operator[ \t]+..." where `...' is
    some legitimate operator text, return a pointer to the
    beginning of the substring of the operator text.
Index: symtab.h
===================================================================
RCS file: /big/fsf/rsync/src-cvs/src/gdb/symtab.h,v
retrieving revision 1.65
diff -u -p -r1.65 symtab.h
--- symtab.h	3 Mar 2003 18:34:12 -0000	1.65
+++ symtab.h	17 Mar 2003 17:07:03 -0000
@@ -1272,6 +1272,9 @@ extern struct symtab *find_line_symtab (
 extern struct symtab_and_line find_function_start_sal (struct symbol *sym,
 						       int);
 
+extern struct symtab_and_line find_msymbol_start_sal (struct minimal_symbol *,
+						      int);
+
 /* symfile.c */
 
 extern void clear_symtab_users (void);



More information about the Gdb-patches mailing list