From 28106bc2feb5553aede17c93fcb01c08bf935ad1 Mon Sep 17 00:00:00 2001 From: Sergio Durigan Junior Date: Fri, 27 Apr 2012 20:48:57 +0000 Subject: [PATCH] 2012-04-27 Sergio Durigan Junior Tom Tromey * breakpoint.c (struct breakpoint_objfile_data) ,,, : 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 | 19 +++++++++++ gdb/breakpoint.c | 86 ++++++++++++++++++++++++++++++++++++++++++++++++ gdb/infrun.c | 77 ++++++++++++++++++++++++++++++++++++------- 3 files changed, 171 insertions(+), 11 deletions(-) diff --git a/gdb/ChangeLog b/gdb/ChangeLog index b2236958928..b047f3505b1 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,22 @@ +2012-04-27 Sergio Durigan Junior + Tom Tromey + + * breakpoint.c (struct breakpoint_objfile_data) + ,,, + : 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 Tom Tromey Jan Kratochvil diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c index 24159743ce9..ab5f3240fb7 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; @@ -2784,6 +2796,15 @@ get_breakpoint_objfile_data (struct objfile *objfile) return bp_objfile_data; } +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) { @@ -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 44254139a83..ab518061f9d 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) { -- 2.30.2