diff options
author | Sergio Durigan Junior <sergiodj@redhat.com> | 2012-04-27 20:48:57 +0000 |
---|---|---|
committer | Sergio Durigan Junior <sergiodj@redhat.com> | 2012-04-27 20:48:57 +0000 |
commit | 28106bc2feb5553aede17c93fcb01c08bf935ad1 (patch) | |
tree | 401179ea78fca6f770f4172c3f12af2c4026832d /gdb | |
parent | 55aa24fb2eb147288fec359a99e960f7136336e8 (diff) | |
download | gdb-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/ChangeLog | 19 | ||||
-rw-r--r-- | gdb/breakpoint.c | 86 | ||||
-rw-r--r-- | gdb/infrun.c | 77 |
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) { |