Mirror of the gdb-patches mailing list
 help / color / mirror / Atom feed
From: Sergio Durigan Junior <sergiodj@redhat.com>
To: gdb-patches@sourceware.org
Cc: Tom Tromey <tromey@redhat.com>
Subject: [PATCH 3/3] Use longjmp and exception probes when available
Date: Fri, 09 Mar 2012 20:34:00 -0000	[thread overview]
Message-ID: <m3lin9bjji.fsf@redhat.com> (raw)
In-Reply-To: <m3boo5cyd8.fsf@redhat.com> (Sergio Durigan Junior's message of	"Fri, 09 Mar 2012 17:28:51 -0300")

Hello,

This is the third and last patch.  It implements the bits necessary for
using longjmp and exception probes on glibc and libgcc, respectively.

Is this OK to check-in?

gdb/ChangeLog
2012-09-03  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.

---
 gdb/breakpoint.c |   89 +++++++++++++++++++++++++++++++++++++++++++++++++++++-
 gdb/infrun.c     |   77 ++++++++++++++++++++++++++++++++++++++++-------
 2 files changed, 154 insertions(+), 12 deletions(-)

diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c
index a8f3a42..7b3f209 100644
--- a/gdb/breakpoint.c
+++ b/gdb/breakpoint.c
@@ -2752,11 +2752,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 (stap_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 (stap_probe_p) *exception_probes;
 };
 
 static const struct objfile_data *breakpoint_objfile_key;
@@ -2793,6 +2805,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 (stap_probe_p, bp_objfile_data->longjmp_probes);
+  VEC_free (stap_probe_p, bp_objfile_data->exception_probes);
+}
+
+static void
 create_overlay_event_breakpoint (void)
 {
   struct objfile *objfile;
@@ -2869,6 +2890,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 stap_probe *probe;
+	  struct gdbarch *gdbarch = get_objfile_arch (objfile);
+
+	  for (i = 0;
+	       VEC_iterate (stap_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 ("-p libc:longjmp");
+	      b->enable_state = bp_disabled;
+	    }
+
+	  continue;
+	}
+
       for (i = 0; i < NUM_LONGJMP_NAMES; i++)
 	{
 	  struct breakpoint *b;
@@ -2979,6 +3031,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 stap_probe *probe;
+
+	  for (i = 0;
+	       VEC_iterate (stap_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 ("-p libgcc:unwind");
+	      b->enable_state = bp_disabled;
+	    }
+
+	  continue;
+	}
+
+      /* Otherwise, try the hook function.  */
+
       if (msym_not_found_p (bp_objfile_data->exception_msym))
 	continue;
 
@@ -15066,7 +15152,8 @@ _initialize_breakpoint (void)
   observer_attach_inferior_exit (clear_syscall_counts);
   observer_attach_memory_changed (invalidate_bp_value_on_memory_change);
 
-  breakpoint_objfile_key = register_objfile_data ();
+  breakpoint_objfile_key
+    = register_objfile_data_with_cleanup (NULL, free_breakpoint_probes);
 
   breakpoint_chain = 0;
   /* Don't bother to call set_breakpoint_count.  $bpnum isn't useful
diff --git a/gdb/infrun.c b/gdb/infrun.c
index 54e39ef..d9bd886 100644
--- a/gdb/infrun.c
+++ b/gdb/infrun.c
@@ -55,6 +55,8 @@
 #include "continuations.h"
 #include "interps.h"
 #include "skip.h"
+#include "stap-probe.h"
+#include "objfiles.h"
 
 /* Prototypes for local functions */
 
@@ -2392,7 +2394,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);
@@ -4427,9 +4429,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 = stap_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,
@@ -4447,12 +4457,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;
 
@@ -5539,15 +5544,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)
 {
   volatile 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)
     {

-- 
Sergio


  parent reply	other threads:[~2012-03-09 20:34 UTC|newest]

Thread overview: 27+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2012-03-09 20:29 [PATCH 0/3] Implement support for SystemTap probes on userspace Sergio Durigan Junior
2012-03-09 20:32 ` [PATCH 1/3] Refactor internal variable mechanism Sergio Durigan Junior
2012-03-09 21:03   ` Tom Tromey
2012-03-10  4:02     ` Sergio Durigan Junior
2012-03-09 20:34 ` Sergio Durigan Junior [this message]
2012-03-09 20:34 ` [PATCH 2/3] Implement new features needed for handling SystemTap probes Sergio Durigan Junior
2012-03-10  8:38   ` Eli Zaretskii
2012-03-10 16:56   ` Mark Kettenis
2012-03-12 15:11     ` Tom Tromey
2012-03-13  8:58       ` Mark Kettenis
2012-03-13 16:06         ` Sergio Durigan Junior
2012-03-15 20:44         ` Tom Tromey
2012-03-16 14:52           ` Mark Kettenis
2012-03-16 18:17             ` Tom Tromey
2012-03-10 19:22   ` Jan Kratochvil
2012-03-12 20:37     ` Tom Tromey
2012-03-12 23:15       ` Jan Kratochvil
2012-03-15 15:40         ` Pedro Alves
2012-03-15 15:36   ` Pedro Alves
2012-03-15 20:50     ` Tom Tromey
2012-03-09 21:15 ` [PATCH 0/3] Implement support for SystemTap probes on userspace Tom Tromey
2012-03-10  3:51   ` Sergio Durigan Junior
2012-03-10  7:55 ` Eli Zaretskii
2012-03-10  8:55   ` Jan Kratochvil
2012-03-10  9:06     ` Eli Zaretskii
2012-03-10 15:52       ` Sergio Durigan Junior
2012-03-12 19:59   ` Tom Tromey

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=m3lin9bjji.fsf@redhat.com \
    --to=sergiodj@redhat.com \
    --cc=gdb-patches@sourceware.org \
    --cc=tromey@redhat.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox