From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 7472 invoked by alias); 9 Mar 2012 20:34:51 -0000 Received: (qmail 7234 invoked by uid 22791); 9 Mar 2012 20:34:47 -0000 X-SWARE-Spam-Status: No, hits=-6.6 required=5.0 tests=AWL,BAYES_00,RCVD_IN_DNSWL_HI,SPF_HELO_PASS,TW_BJ,TW_GJ,T_RP_MATCHES_RCVD X-Spam-Check-By: sourceware.org Received: from mx1.redhat.com (HELO mx1.redhat.com) (209.132.183.28) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Fri, 09 Mar 2012 20:34:30 +0000 Received: from int-mx09.intmail.prod.int.phx2.redhat.com (int-mx09.intmail.prod.int.phx2.redhat.com [10.5.11.22]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id q29KYUqr015707 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK) for ; Fri, 9 Mar 2012 15:34:30 -0500 Received: from psique (ovpn-112-58.phx2.redhat.com [10.3.112.58]) by int-mx09.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id q29KYQZx009002; Fri, 9 Mar 2012 15:34:28 -0500 From: Sergio Durigan Junior To: gdb-patches@sourceware.org Cc: Tom Tromey Subject: [PATCH 3/3] Use longjmp and exception probes when available References: X-URL: http://www.redhat.com Date: Fri, 09 Mar 2012 20:34:00 -0000 In-Reply-To: (Sergio Durigan Junior's message of "Fri, 09 Mar 2012 17:28:51 -0300") Message-ID: User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/23.3 (gnu/linux) MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii X-IsSubscribed: yes Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org X-SW-Source: 2012-03/txt/msg00356.txt.bz2 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 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/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