This is the mail archive of the gdb-patches@sourceware.org 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]
Other format: [Raw text]

[PATCH 5/6] Make exception handling use SystemTap probes


Hi,

This patch updates GDB to use the SystemTap probe in the libgccj
unwinder if it is available.  This probe is in GCC SVN and in the
(forthcoming) Fedora 15 libgcc.  The probe point is preferred over the
unwind hook because it can be use without debuginfo.

We tested this patch in a Fedora 15 mock chroot.

This was regtested on the compile farm.

Thanks,

Sergio.

---
 gdb/ChangeLog    |   14 ++++++++++++
 gdb/breakpoint.c |   31 ++++++++++++++++++++++++++
 gdb/infrun.c     |   63 +++++++++++++++++++++++++++++++++++++++++++++++------
 3 files changed, 100 insertions(+), 8 deletions(-)

diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 28e4711..1b0b0d2 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,3 +1,17 @@
+2011-04-04  Tom Tromey  <tromey@redhat.com>
+
+	* breakpoint.c (struct breakpoint_objfile_data) <exception_probe>: New
+	field.
+	(probe_not_found): New variable.
+	(create_exception_master_breakpoint): Prefer SystemTap probe over
+	`_Unwind_DebugHook'.
+	* infrun.c: Add `stap-probe.h' and `objfiles.h'.
+	(check_exception_resume): Remove `struct symbol *' argument.
+	(handle_inferior_event): Update.
+	(insert_exception_resume_from_probe): New function.
+	(check_exception_resume): Remove `func' argument.  Handle exception
+	unwinding breakpoint set via a SystemTap probe.
+
 2011-04-04 Sergio Durigan Junior  <sergiodj@redhat.com>
 	    Tom Tromey  <tromey@redhat.com>
 
diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c
index 8850f34..7e32276 100644
--- a/gdb/breakpoint.c
+++ b/gdb/breakpoint.c
@@ -2154,10 +2154,16 @@ struct breakpoint_objfile_data
 
   /* Minimal symbol for "_Unwind_DebugHook" (if any).  */
   struct minimal_symbol *exception_msym;
+
+  /* SystemTap probe point for unwinding (if any).  */
+  const struct stap_probe *exception_probe;
 };
 
 static const struct objfile_data *breakpoint_objfile_key;
 
+/* SystemTap probe not found sentinel.  */
+static const struct stap_probe probe_not_found;
+
 /* Minimal symbol not found sentinel.  */
 static struct minimal_symbol msym_not_found;
 
@@ -2373,6 +2379,31 @@ create_exception_master_breakpoint (void)
 
       bp_objfile_data = get_breakpoint_objfile_data (objfile);
 
+      /* We prefer the SystemTap probe point if it exists.  */
+      if (bp_objfile_data->exception_probe != &probe_not_found)
+	{
+	  if (bp_objfile_data->exception_probe == NULL)
+	    bp_objfile_data->exception_probe
+	      = find_probe_in_objfile (objfile, "libgcc", "unwind");
+
+	  if (bp_objfile_data->exception_probe)
+	    {
+	      struct breakpoint *b;
+	      struct gdbarch *gdbarch = get_objfile_arch (objfile);
+
+	      b = create_internal_breakpoint (gdbarch,
+					      bp_objfile_data->exception_probe->address,
+					      bp_exception_master);
+	      b->addr_string = xstrdup ("probe:libgcc:unwind");
+	      b->enable_state = bp_disabled;
+	      continue;
+	    }
+	  else
+	    bp_objfile_data->exception_probe = &probe_not_found;
+	}
+
+      /* Otherwise, try the hook function.  */
+
       if (msym_not_found_p (bp_objfile_data->exception_msym))
 	continue;
 
diff --git a/gdb/infrun.c b/gdb/infrun.c
index 77d8da8..2c9cad8 100644
--- a/gdb/infrun.c
+++ b/gdb/infrun.c
@@ -54,6 +54,8 @@
 #include "inline-frame.h"
 #include "jit.h"
 #include "tracepoint.h"
+#include "stap-probe.h"
+#include "objfiles.h"
 
 /* Prototypes for local functions */
 
@@ -2247,7 +2249,7 @@ static void insert_step_resume_breakpoint_at_sal (struct gdbarch *,
 						  struct frame_id);
 static void insert_longjmp_resume_breakpoint (struct gdbarch *, CORE_ADDR);
 static void check_exception_resume (struct execution_control_state *,
-				    struct frame_info *, struct symbol *);
+				    struct frame_info *);
 
 static void stop_stepping (struct execution_control_state *ecs);
 static void prepare_to_wait (struct execution_control_state *ecs);
@@ -4184,12 +4186,7 @@ process_event_stop_test:
 	    insert_longjmp_resume_breakpoint (gdbarch, jmp_buf_pc);
 	  }
 	else
-	  {
-	    struct symbol *func = get_frame_function (frame);
-
-	    if (func)
-	      check_exception_resume (ecs, frame, func);
-	  }
+	  check_exception_resume (ecs, frame);
 	keep_going (ecs);
 	return;
 
@@ -5263,15 +5260,65 @@ insert_exception_resume_breakpoint (struct thread_info *tp,
     }
 }
 
+/* A helper for check_exception_resume that sets an
+   exception-breakpoint based on a SystemTap probe.  */
+
+static void
+insert_exception_resume_from_probe (struct thread_info *tp,
+				    const struct stap_probe *probe,
+				    struct objfile *objfile,
+				    struct frame_info *frame)
+{
+  struct value *arg_value;
+  CORE_ADDR handler;
+  struct breakpoint *bp;
+
+  arg_value = stap_safe_evaluate_at_pc (frame, 1);
+  if (!arg_value)
+    return;
+
+  handler = value_as_address (arg_value);
+
+  if (debug_infrun)
+    fprintf_unfiltered (gdb_stdlog,
+			"infrun: exception resume at %s\n",
+			paddress (get_objfile_arch (objfile),
+				  handler));
+
+  bp = set_momentary_breakpoint_at_pc (get_frame_arch (frame),
+				       handler, bp_exception_resume);
+  bp->thread = tp->num;
+  inferior_thread ()->control.exception_resume_breakpoint = bp;
+}
+
 /* This is called when an exception has been intercepted.  Check to
    see whether the exception's destination is of interest, and if so,
    set an exception resume breakpoint there.  */
 
 static void
 check_exception_resume (struct execution_control_state *ecs,
-			struct frame_info *frame, struct symbol *func)
+			struct frame_info *frame)
 {
   struct gdb_exception e;
+  struct objfile *objfile;
+  const struct stap_probe *probe;
+  struct symbol *func;
+
+  /* First see if this exception unwinding breakpoint was set via a
+     SystemTap probe point.  If so, the probe has two arguments: the
+     CFA and the HANDLER.  We ignore the CFA, extract the handler, and
+     set a breakpoint there.  */
+  probe = find_probe_by_pc (get_frame_pc (frame), &objfile);
+  if (probe)
+    {
+      insert_exception_resume_from_probe (ecs->event_thread, probe,
+					  objfile, frame);
+      return;
+    }
+
+  func = get_frame_function (frame);
+  if (!func)
+    return;
 
   TRY_CATCH (e, RETURN_MASK_ERROR)
     {


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