2012-04-27 Sergio Durigan Junior <sergiodj@redhat.com>
authorSergio Durigan Junior <sergiodj@redhat.com>
Fri, 27 Apr 2012 20:48:57 +0000 (20:48 +0000)
committerSergio Durigan Junior <sergiodj@redhat.com>
Fri, 27 Apr 2012 20:48:57 +0000 (20:48 +0000)
    Tom Tromey  <tromey@redhat.com>

* breakpoint.c (struct breakpoint_objfile_data)
<longjmp_searched>,<longjmp_probes>,<exception_searched>,
<exception_probes>: New fields.
(free_breakpoint_probes): New function.
(create_longjmp_master_breakpoint): Prefer SystemTap probe over
`_Unwind_DebugHook'.
(create_exception_master_breakpoint): Likewise.
(_initialize_breakpoint): Registering cleanup for SystemTap probes.
* infrun.c: Including necessary header files for handling SystemTap
probes.
(handle_inferior_event): Handling longjmp breakpoint and exceptions
via SystemTap probes.
(check_exception_resume): Remove `func' argument.  Handle exception
unwinding breakpoint set via a SystemTap probe.
(insert_exception_resume_from_probe): New function.

gdb/ChangeLog
gdb/breakpoint.c
gdb/infrun.c

index b223695..b047f35 100644 (file)
@@ -1,5 +1,24 @@
 2012-04-27  Sergio Durigan Junior  <sergiodj@redhat.com>
            Tom Tromey  <tromey@redhat.com>
+
+       * breakpoint.c (struct breakpoint_objfile_data)
+       <longjmp_searched>,<longjmp_probes>,<exception_searched>,
+       <exception_probes>: New fields.
+       (free_breakpoint_probes): New function.
+       (create_longjmp_master_breakpoint): Prefer SystemTap probe over
+       `_Unwind_DebugHook'.
+       (create_exception_master_breakpoint): Likewise.
+       (_initialize_breakpoint): Registering cleanup for SystemTap probes.
+       * infrun.c: Including necessary header files for handling SystemTap
+       probes.
+       (handle_inferior_event): Handling longjmp breakpoint and exceptions
+       via SystemTap probes.
+       (check_exception_resume): Remove `func' argument.  Handle exception
+       unwinding breakpoint set via a SystemTap probe.
+       (insert_exception_resume_from_probe): New function.
+
+2012-04-27  Sergio Durigan Junior  <sergiodj@redhat.com>
+           Tom Tromey  <tromey@redhat.com>
            Jan Kratochvil  <jan.kratochvil@redhat.com>
 
        * Makefile.in (SFILES): Add `probe' and `stap-probe'.
index 2415974..ab5f324 100644 (file)
@@ -2744,11 +2744,23 @@ struct breakpoint_objfile_data
   /* Minimal symbol(s) for "longjmp", "siglongjmp", etc. (if any).  */
   struct minimal_symbol *longjmp_msym[NUM_LONGJMP_NAMES];
 
+  /* True if we have looked for longjmp probes.  */
+  int longjmp_searched;
+
+  /* SystemTap probe points for longjmp (if any).  */
+  VEC (probe_p) *longjmp_probes;
+
   /* Minimal symbol for "std::terminate()" (if any).  */
   struct minimal_symbol *terminate_msym;
 
   /* Minimal symbol for "_Unwind_DebugHook" (if any).  */
   struct minimal_symbol *exception_msym;
+
+  /* True if we have looked for exception probes.  */
+  int exception_searched;
+
+  /* SystemTap probe points for unwinding (if any).  */
+  VEC (probe_p) *exception_probes;
 };
 
 static const struct objfile_data *breakpoint_objfile_key;
@@ -2785,6 +2797,15 @@ get_breakpoint_objfile_data (struct objfile *objfile)
 }
 
 static void
+free_breakpoint_probes (struct objfile *obj, void *data)
+{
+  struct breakpoint_objfile_data *bp_objfile_data = data;
+
+  VEC_free (probe_p, bp_objfile_data->longjmp_probes);
+  VEC_free (probe_p, bp_objfile_data->exception_probes);
+}
+
+static void
 create_overlay_event_breakpoint (void)
 {
   struct objfile *objfile;
@@ -2861,6 +2882,37 @@ create_longjmp_master_breakpoint (void)
 
       bp_objfile_data = get_breakpoint_objfile_data (objfile);
 
+      if (!bp_objfile_data->longjmp_searched)
+       {
+         bp_objfile_data->longjmp_probes
+           = find_probes_in_objfile (objfile, "libc", "longjmp");
+         bp_objfile_data->longjmp_searched = 1;
+       }
+
+      if (bp_objfile_data->longjmp_probes != NULL)
+       {
+         int i;
+         struct probe *probe;
+         struct gdbarch *gdbarch = get_objfile_arch (objfile);
+
+         for (i = 0;
+              VEC_iterate (probe_p,
+                           bp_objfile_data->longjmp_probes,
+                           i, probe);
+              ++i)
+           {
+             struct breakpoint *b;
+
+             b = create_internal_breakpoint (gdbarch, probe->address,
+                                             bp_longjmp_master,
+                                             &internal_breakpoint_ops);
+             b->addr_string = xstrdup ("-probe-stap libc:longjmp");
+             b->enable_state = bp_disabled;
+           }
+
+         continue;
+       }
+
       for (i = 0; i < NUM_LONGJMP_NAMES; i++)
        {
          struct breakpoint *b;
@@ -2971,6 +3023,40 @@ 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_searched)
+       {
+         bp_objfile_data->exception_probes
+           = find_probes_in_objfile (objfile, "libgcc", "unwind");
+         bp_objfile_data->exception_searched = 1;
+       }
+
+      if (bp_objfile_data->exception_probes != NULL)
+       {
+         struct gdbarch *gdbarch = get_objfile_arch (objfile);
+         int i;
+         struct probe *probe;
+
+         for (i = 0;
+              VEC_iterate (probe_p,
+                           bp_objfile_data->exception_probes,
+                           i, probe);
+              ++i)
+           {
+             struct breakpoint *b;
+
+             b = create_internal_breakpoint (gdbarch, probe->address,
+                                             bp_exception_master,
+                                             &internal_breakpoint_ops);
+             b->addr_string = xstrdup ("-probe-stap libgcc:unwind");
+             b->enable_state = bp_disabled;
+           }
+
+         continue;
+       }
+
+      /* Otherwise, try the hook function.  */
+
       if (msym_not_found_p (bp_objfile_data->exception_msym))
        continue;
 
index 4425413..ab51806 100644 (file)
@@ -55,6 +55,8 @@
 #include "continuations.h"
 #include "interps.h"
 #include "skip.h"
+#include "probe.h"
+#include "objfiles.h"
 
 /* Prototypes for local functions */
 
@@ -2402,7 +2404,7 @@ static void handle_step_into_function (struct gdbarch *gdbarch,
 static void handle_step_into_function_backward (struct gdbarch *gdbarch,
                                                struct execution_control_state *ecs);
 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);
@@ -4437,9 +4439,17 @@ process_event_stop_test:
 
        if (what.is_longjmp)
          {
-           if (!gdbarch_get_longjmp_target_p (gdbarch)
-               || !gdbarch_get_longjmp_target (gdbarch,
-                                               frame, &jmp_buf_pc))
+           struct value *arg_value;
+
+           /* If we set the longjmp breakpoint via a SystemTap probe,
+              then use it to extract the arguments.  The destination
+              PC is the third argument to the probe.  */
+           arg_value = probe_safe_evaluate_at_pc (frame, 2);
+           if (arg_value)
+             jmp_buf_pc = value_as_address (arg_value);
+           else if (!gdbarch_get_longjmp_target_p (gdbarch)
+                    || !gdbarch_get_longjmp_target (gdbarch,
+                                                    frame, &jmp_buf_pc))
              {
                if (debug_infrun)
                  fprintf_unfiltered (gdb_stdlog,
@@ -4457,12 +4467,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;
 
@@ -5552,15 +5557,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 probe *probe,
+                                   struct objfile *objfile,
+                                   struct frame_info *frame)
+{
+  struct value *arg_value;
+  CORE_ADDR handler;
+  struct breakpoint *bp;
+
+  arg_value = probe_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)
 {
   volatile struct gdb_exception e;
+  struct objfile *objfile;
+  const struct 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)
     {