From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 15800 invoked by alias); 10 Feb 2011 18:42:08 -0000 Mailing-List: contact archer-commits-help@sourceware.org; run by ezmlm Sender: Precedence: bulk List-Post: List-Help: List-Subscribe: Received: (qmail 15772 invoked by uid 306); 10 Feb 2011 18:42:07 -0000 Date: Thu, 10 Feb 2011 18:42:00 -0000 Message-ID: <20110210184207.15757.qmail@sourceware.org> From: tromey@sourceware.org To: archer-commits@sourceware.org Subject: [SCM] archer-sergiodj-stap: make exception-related breakpoints use stap probes when available this is untested; it needs the probe arguments to work first X-Git-Refname: refs/heads/archer-sergiodj-stap X-Git-Reftype: branch X-Git-Oldrev: 1b16efd7055bbe6ff5029ecc36df9b8a04704799 X-Git-Newrev: 0fec3a3d8f23a141e2647927375981029355ab3f X-SW-Source: 2011-q1/txt/msg00106.txt.bz2 List-Id: The branch, archer-sergiodj-stap has been updated via 0fec3a3d8f23a141e2647927375981029355ab3f (commit) from 1b16efd7055bbe6ff5029ecc36df9b8a04704799 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email. - Log ----------------------------------------------------------------- commit 0fec3a3d8f23a141e2647927375981029355ab3f Author: Tom Tromey Date: Thu Feb 10 11:41:30 2011 -0700 make exception-related breakpoints use stap probes when available this is untested; it needs the probe arguments to work first ----------------------------------------------------------------------- Summary of changes: gdb/breakpoint.c | 15 +++++++++++ gdb/infrun.c | 75 ++++++++++++++++++++++++++++++++++++++++++++++++------ gdb/stap-probe.c | 67 ++++++++++++++++++++++++++++++++++++----------- gdb/stap-probe.h | 14 ++++++++++ 4 files changed, 147 insertions(+), 24 deletions(-) First 500 lines of diff: diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c index 3c59f11..8390be8 100644 --- a/gdb/breakpoint.c +++ b/gdb/breakpoint.c @@ -63,6 +63,7 @@ #include "xml-syscall.h" #include "parser-defs.h" #include "gdb_regex.h" +#include "stap-probe.h" /* readline include files */ #include "readline/readline.h" @@ -2269,6 +2270,20 @@ create_exception_master_breakpoint (void) ALL_OBJFILES (objfile) { struct minimal_symbol *debug_hook; + const struct stap_probe *probe; + + probe = find_probe_in_objfile (objfile, "libgcc", "unwind"); + if (probe != NULL) + { + struct breakpoint *b; + struct gdbarch *gdbarch = get_objfile_arch (objfile); + + b = create_internal_breakpoint (gdbarch, probe->address, + bp_exception_master); + b->addr_string = xstrdup ("probe:libgcc:unwind"); + b->enable_state = bp_disabled; + continue; + } debug_hook = lookup_minimal_symbol ("_Unwind_DebugHook", NULL, objfile); if (debug_hook != NULL) diff --git a/gdb/infrun.c b/gdb/infrun.c index 6fdd9df..8bf8a57 100644 --- a/gdb/infrun.c +++ b/gdb/infrun.c @@ -54,6 +54,8 @@ #include "inline-frame.h" #include "jit.h" #include "tracepoint.h" +#include "stap-probe.h" +#include "objfiles.h" /* Prototypes for local functions */ @@ -2239,7 +2241,7 @@ static void insert_step_resume_breakpoint_at_sal (struct gdbarch *, struct frame_id); static void insert_longjmp_resume_breakpoint (struct gdbarch *, CORE_ADDR); 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); @@ -4166,12 +4168,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; @@ -5246,15 +5243,77 @@ 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) +{ + int n_probes; + struct value *arg_value; + CORE_ADDR handler; + struct breakpoint *bp; + + /* This is really a "can't happen", but we are paranoid. */ + if (!objfile->sf || !objfile->sf->sym_probe_fns) + return; + + n_probes + = objfile->sf->sym_probe_fns->sym_get_probe_argument_count (objfile, + probe); + if (n_probes < 2) + return; + + /* We are interested in the second argument to the probe. */ + arg_value + = objfile->sf->sym_probe_fns->sym_evaluate_probe_argument (objfile, + probe, + frame, + 1); + handler = value_as_address (arg_value); + + if (debug_infrun) + fprintf_unfiltered (gdb_stdlog, + "infrun: exception resume at %lx\n", + (unsigned long) 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) { 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) { diff --git a/gdb/stap-probe.c b/gdb/stap-probe.c index 7230a49..ccca946 100644 --- a/gdb/stap-probe.c +++ b/gdb/stap-probe.c @@ -265,6 +265,32 @@ info_probes_command (char *arg, int from_tty) +const struct stap_probe * +find_probe_in_objfile (struct objfile *objfile, + const char *provider, + const char *name) +{ + const struct stap_probe *probes; + int i, num_probes; + + if (! objfile->sf || ! objfile->sf->sym_probe_fns) + return NULL; + + probes = objfile->sf->sym_probe_fns->sym_get_probes (objfile, &num_probes); + for (i = 0; i < num_probes; ++i) + { + if (strcmp (probes[i].provider, provider) != 0) + continue; + + if (strcmp (probes[i].name, name) != 0) + continue; + + return &probes[i]; + } + + return NULL; +} + struct symtabs_and_lines parse_stap_probe (char **argptr) { @@ -370,22 +396,10 @@ parse_stap_probe (char **argptr) -/* This is called to compute the value of one of the $_marker_arg* - convenience variables. */ - -static struct value * -compute_marker_arg (struct gdbarch *arch, struct internalvar *ivar, - void *data) +const struct stap_probe * +find_probe_by_pc (CORE_ADDR pc, struct objfile **objfile_out) { - struct frame_info *frame = get_selected_frame (_("No frame selected")); - CORE_ADDR pc = get_frame_pc (frame); - int sel = (int) (uintptr_t) data; struct objfile *objfile; - const struct stap_probe *pc_probe = NULL; - int n_probes; - - /* Note that SEL is biased by 1; SEL==0 means "_marker_argc". */ - gdb_assert (sel >= 0 && sel <= 10); ALL_OBJFILES (objfile) { @@ -402,12 +416,33 @@ compute_marker_arg (struct gdbarch *arch, struct internalvar *ivar, { if (probes[i].address == pc) { - pc_probe = &probes[i]; - break; + *objfile_out = objfile; + return &probes[i]; } } } + return NULL; +} + +/* This is called to compute the value of one of the $_marker_arg* + convenience variables. */ + +static struct value * +compute_marker_arg (struct gdbarch *arch, struct internalvar *ivar, + void *data) +{ + struct frame_info *frame = get_selected_frame (_("No frame selected")); + CORE_ADDR pc = get_frame_pc (frame); + int sel = (int) (uintptr_t) data; + struct objfile *objfile; + const struct stap_probe *pc_probe; + int n_probes; + + /* Note that SEL is biased by 1; SEL==0 means "_marker_argc". */ + gdb_assert (sel >= 0 && sel <= 10); + + pc_probe = find_probe_by_pc (pc, &objfile); if (pc_probe == NULL) error (_("No SystemTap probe at PC %s"), core_addr_to_string (pc)); diff --git a/gdb/stap-probe.h b/gdb/stap-probe.h index 1967e7b..c7d8e7f 100644 --- a/gdb/stap-probe.h +++ b/gdb/stap-probe.h @@ -45,4 +45,18 @@ struct stap_probe extern struct symtabs_and_lines parse_stap_probe (char **argptr); +/* Search OBJFILE for a probe with the given PROVIDER and NAME. If a + probe is found, return it. If no probe is found, return NULL. */ + +extern const struct stap_probe *find_probe_in_objfile (struct objfile *objfile, + const char *provider, + const char *name); + +/* Given a PC, find an associated SystemTap probe. If a probe is + found, set *OBJFILE_OUT to the probe's objfile, and return the + probe. If no probe is found, return NULL. */ + +extern const struct stap_probe *find_probe_by_pc (CORE_ADDR pc, + struct objfile **objfile_out); + #endif /* !defined (STAP_PROBE_H) */ hooks/post-receive -- Repository for Project Archer.