aboutsummaryrefslogtreecommitdiff
path: root/gdb
diff options
context:
space:
mode:
authorSergio Durigan Junior <sergiodj@redhat.com>2012-04-27 20:48:57 +0000
committerSergio Durigan Junior <sergiodj@redhat.com>2012-04-27 20:48:57 +0000
commit28106bc2feb5553aede17c93fcb01c08bf935ad1 (patch)
tree401179ea78fca6f770f4172c3f12af2c4026832d /gdb
parent55aa24fb2eb147288fec359a99e960f7136336e8 (diff)
downloadgdb-28106bc2feb5553aede17c93fcb01c08bf935ad1.zip
gdb-28106bc2feb5553aede17c93fcb01c08bf935ad1.tar.gz
gdb-28106bc2feb5553aede17c93fcb01c08bf935ad1.tar.bz2
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.
Diffstat (limited to 'gdb')
-rw-r--r--gdb/ChangeLog19
-rw-r--r--gdb/breakpoint.c86
-rw-r--r--gdb/infrun.c77
3 files changed, 171 insertions, 11 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index b223695..b047f35 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -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'.
diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c
index 2415974..ab5f324 100644
--- a/gdb/breakpoint.c
+++ b/gdb/breakpoint.c
@@ -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;
diff --git a/gdb/infrun.c b/gdb/infrun.c
index 4425413..ab51806 100644
--- a/gdb/infrun.c
+++ b/gdb/infrun.c
@@ -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)
{