From patchwork Tue Jul 5 13:40:25 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Antoine Tremblay X-Patchwork-Id: 13649 Received: (qmail 65917 invoked by alias); 5 Jul 2016 13:41:44 -0000 Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org Delivered-To: mailing list gdb-patches@sourceware.org Received: (qmail 65811 invoked by uid 89); 5 Jul 2016 13:41:43 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=0.6 required=5.0 tests=BAYES_00, KAM_LAZY_DOMAIN_SECURITY, KAM_STOCKGEN autolearn=no version=3.3.2 spammy=agents, collect, longest, inn X-HELO: usplmg21.ericsson.net Received: from usplmg21.ericsson.net (HELO usplmg21.ericsson.net) (198.24.6.65) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with (AES256-SHA encrypted) ESMTPS; Tue, 05 Jul 2016 13:41:31 +0000 Received: from EUSAAHC008.ericsson.se (Unknown_Domain [147.117.188.96]) by usplmg21.ericsson.net (Symantec Mail Security) with SMTP id BA.66.03614.1B8BB775; Tue, 5 Jul 2016 15:40:02 +0200 (CEST) Received: from elxa4wqvvz1.dyn.mo.ca.am.ericsson.se (147.117.188.8) by smtps-am.internal.ericsson.com (147.117.188.96) with Microsoft SMTP Server (TLS) id 14.3.294.0; Tue, 5 Jul 2016 09:40:54 -0400 From: Antoine Tremblay To: CC: Antoine Tremblay Subject: [PATCH v3 13/18] Export tracing control breakpoints functions via global function pointers Date: Tue, 5 Jul 2016 09:40:25 -0400 Message-ID: <1467726030-13020-14-git-send-email-antoine.tremblay@ericsson.com> In-Reply-To: <1467726030-13020-1-git-send-email-antoine.tremblay@ericsson.com> References: <1467726030-13020-1-git-send-email-antoine.tremblay@ericsson.com> MIME-Version: 1.0 X-IsSubscribed: yes Since ARM has 2 instructions sets ARM, and Thumb and thus 2 breakpoint instructions. GDBServer needs to know what kind of breakpoint to set in the IPA for it's tracing controls breakpoints (stop_tracing, flush_trace_buffer, about_to_request_buffer_space). Since qSymbol does not carry the Thumb bit on the symbol address, this patch exports a function pointer with the address of the function to be read by GDBServer. This way the Thumb bit is carried in that value and GDBServer sets the proper breakpoint. This patch adds a test that collects 10MB of data, so that a flush is triggered after the IPA reaches its 5MB limit. gdb/gdbserver/ChangeLog: * tracepoint.c (stop_tracing, flush_trace_buffer, about_to_request_buffer_space): Rename with _ptr suffix. (struct ipa_sym_addresses): Likewise. (symbol_list): Likewise. (stop_tracing): Remove function export. (flush_trace_buffer): Likewise. (about_to_request_buffer_space): Likewise. (cmd_qtstart): Read breakpoint addresses from the inferior. (handle_tracepoint_bkpts): Likewise. (stop_tracing_ptr, flush_trace_buffer_ptr, (tracepoint_bkpt_ptr_type): New typedef. about_to_request_buffer_space_ptr): New globals. (upload_fast_traceframes): Read breakpoint address from the inferior. gdb/testsuite/ChangeLog: * ftrace-flush-buffer.exp: New file. * ftrace-flush-buffer.c: Likewise. --- gdb/gdbserver/tracepoint.c | 94 ++++++++++++++++++------ gdb/testsuite/gdb.trace/ftrace-flush-buffer.c | 42 +++++++++++ gdb/testsuite/gdb.trace/ftrace-flush-buffer.exp | 98 +++++++++++++++++++++++++ 3 files changed, 213 insertions(+), 21 deletions(-) create mode 100644 gdb/testsuite/gdb.trace/ftrace-flush-buffer.c create mode 100644 gdb/testsuite/gdb.trace/ftrace-flush-buffer.exp diff --git a/gdb/gdbserver/tracepoint.c b/gdb/gdbserver/tracepoint.c index a139f67..87211e9 100644 --- a/gdb/gdbserver/tracepoint.c +++ b/gdb/gdbserver/tracepoint.c @@ -109,9 +109,9 @@ trace_vdebug (const char *fmt, ...) # define gdb_trampoline_buffer_error IPA_SYM_EXPORTED_NAME (gdb_trampoline_buffer_error) # define collecting IPA_SYM_EXPORTED_NAME (collecting) # define gdb_collect_ptr IPA_SYM_EXPORTED_NAME (gdb_collect_ptr) -# define stop_tracing IPA_SYM_EXPORTED_NAME (stop_tracing) -# define flush_trace_buffer IPA_SYM_EXPORTED_NAME (flush_trace_buffer) -# define about_to_request_buffer_space IPA_SYM_EXPORTED_NAME (about_to_request_buffer_space) +# define stop_tracing_ptr IPA_SYM_EXPORTED_NAME (stop_tracing_ptr) +# define flush_trace_buffer_ptr IPA_SYM_EXPORTED_NAME (flush_trace_buffer_ptr) +# define about_to_request_buffer_space_ptr IPA_SYM_EXPORTED_NAME (about_to_request_buffer_space_ptr) # define trace_buffer_is_full IPA_SYM_EXPORTED_NAME (trace_buffer_is_full) # define stopping_tracepoint IPA_SYM_EXPORTED_NAME (stopping_tracepoint) # define expr_eval_result IPA_SYM_EXPORTED_NAME (expr_eval_result) @@ -151,9 +151,9 @@ struct ipa_sym_addresses CORE_ADDR addr_gdb_trampoline_buffer_error; CORE_ADDR addr_collecting; CORE_ADDR addr_gdb_collect_ptr; - CORE_ADDR addr_stop_tracing; - CORE_ADDR addr_flush_trace_buffer; - CORE_ADDR addr_about_to_request_buffer_space; + CORE_ADDR addr_stop_tracing_ptr; + CORE_ADDR addr_flush_trace_buffer_ptr; + CORE_ADDR addr_about_to_request_buffer_space_ptr; CORE_ADDR addr_trace_buffer_is_full; CORE_ADDR addr_stopping_tracepoint; CORE_ADDR addr_expr_eval_result; @@ -188,9 +188,9 @@ static struct IPA_SYM(gdb_trampoline_buffer_error), IPA_SYM(collecting), IPA_SYM(gdb_collect_ptr), - IPA_SYM(stop_tracing), - IPA_SYM(flush_trace_buffer), - IPA_SYM(about_to_request_buffer_space), + IPA_SYM(stop_tracing_ptr), + IPA_SYM(flush_trace_buffer_ptr), + IPA_SYM(about_to_request_buffer_space_ptr), IPA_SYM(trace_buffer_is_full), IPA_SYM(stopping_tracepoint), IPA_SYM(expr_eval_result), @@ -368,14 +368,14 @@ read_inferior_memory (CORE_ADDR memaddr, unsigned char *myaddr, int len) # define UNKNOWN_SIDE_EFFECTS() do {} while (0) #endif -IP_AGENT_EXPORT_FUNC void +void stop_tracing (void) { /* GDBserver places breakpoint here. */ UNKNOWN_SIDE_EFFECTS(); } -IP_AGENT_EXPORT_FUNC void +void flush_trace_buffer (void) { /* GDBserver places breakpoint here. */ @@ -1379,7 +1379,7 @@ init_trace_buffer (LONGEST bufsize) #ifdef IN_PROCESS_AGENT -IP_AGENT_EXPORT_FUNC void +void about_to_request_buffer_space (void) { /* GDBserver places breakpoint here while it goes about to flush @@ -3095,6 +3095,7 @@ cmd_qtstart (char *packet) { struct tracepoint *tpoint, *prev_ftpoint, *prev_stpoint; CORE_ADDR tpptr = 0, prev_tpptr = 0; + CORE_ADDR addr_flush_trace_buffer, addr_stop_tracing; trace_debug ("Starting the trace"); @@ -3291,14 +3292,29 @@ cmd_qtstart (char *packet) " in lib"); } - stop_tracing_bkpt = set_breakpoint_at (ipa_sym_addrs.addr_stop_tracing, + if (read_inferior_data_pointer (ipa_sym_addrs.addr_stop_tracing_ptr, + &addr_stop_tracing)) + { + internal_error (__FILE__, __LINE__, + "Error reading addr_stop_tracing_ptr variable" + " in lib"); + } + + stop_tracing_bkpt = set_breakpoint_at (addr_stop_tracing, stop_tracing_handler); if (stop_tracing_bkpt == NULL) error ("Error setting stop_tracing breakpoint"); - flush_trace_buffer_bkpt - = set_breakpoint_at (ipa_sym_addrs.addr_flush_trace_buffer, - flush_trace_buffer_handler); + if (read_inferior_data_pointer (ipa_sym_addrs.addr_flush_trace_buffer_ptr, + &addr_flush_trace_buffer)) + { + internal_error (__FILE__, __LINE__, + "Error reading addr_flsh_trace_ptr variable" + " in lib"); + } + + flush_trace_buffer_bkpt = set_breakpoint_at (addr_flush_trace_buffer, + flush_trace_buffer_handler); if (flush_trace_buffer_bkpt == NULL) error ("Error setting flush_trace_buffer breakpoint"); } @@ -4385,6 +4401,8 @@ tracepoint_finished_step (struct thread_info *tinfo, CORE_ADDR stop_pc) int handle_tracepoint_bkpts (struct thread_info *tinfo, CORE_ADDR stop_pc) { + CORE_ADDR addr_stop_tracing, addr_flush_trace_buffer; + /* Pull in fast tracepoint trace frames from the inferior in-process agent's buffer into our buffer. */ @@ -4393,9 +4411,25 @@ handle_tracepoint_bkpts (struct thread_info *tinfo, CORE_ADDR stop_pc) upload_fast_traceframes (); + if (read_inferior_data_pointer (ipa_sym_addrs.addr_stop_tracing_ptr, + &addr_stop_tracing)) + { + internal_error (__FILE__, __LINE__, + "Error reading addr_stop_tracing_ptr variable" + " in lib"); + } + + if (read_inferior_data_pointer (ipa_sym_addrs.addr_flush_trace_buffer_ptr, + &addr_flush_trace_buffer)) + { + internal_error (__FILE__, __LINE__, + "Error reading addr_flsh_trace_ptr variable" + " in lib"); + } + /* Check if the in-process agent had decided we should stop tracing. */ - if (stop_pc == ipa_sym_addrs.addr_stop_tracing) + if (stop_pc == addr_stop_tracing) { int ipa_trace_buffer_is_full; CORE_ADDR ipa_stopping_tracepoint; @@ -4452,7 +4486,7 @@ handle_tracepoint_bkpts (struct thread_info *tinfo, CORE_ADDR stop_pc) stop_tracing (); return 1; } - else if (stop_pc == ipa_sym_addrs.addr_flush_trace_buffer) + else if (stop_pc == addr_flush_trace_buffer) { trace_debug ("lib stopped at flush_trace_buffer"); return 1; @@ -5774,12 +5808,16 @@ gdb_collect (struct tracepoint *tpoint, unsigned char *regs) /* These global variables points to the corresponding functions. This is necessary on powerpc64, where asking for function symbol address from gdb results in returning the actual code pointer, instead of the descriptor - pointer. */ + pointer. + These variables are also needed for ARM so that the address contains the + Thumb bit if the address is in thumb mode. + */ typedef void (*gdb_collect_ptr_type) (struct tracepoint *, unsigned char *); typedef ULONGEST (*get_raw_reg_ptr_type) (const unsigned char *, int); typedef LONGEST (*get_trace_state_variable_value_ptr_type) (int); typedef void (*set_trace_state_variable_value_ptr_type) (int, LONGEST); +typedef void (*tracepoint_bkpt_ptr_type) (void); EXTERN_C_PUSH IP_AGENT_EXPORT_VAR gdb_collect_ptr_type gdb_collect_ptr = gdb_collect; @@ -5788,6 +5826,11 @@ IP_AGENT_EXPORT_VAR get_trace_state_variable_value_ptr_type get_trace_state_variable_value_ptr = get_trace_state_variable_value; IP_AGENT_EXPORT_VAR set_trace_state_variable_value_ptr_type set_trace_state_variable_value_ptr = set_trace_state_variable_value; +IP_AGENT_EXPORT_VAR tracepoint_bkpt_ptr_type stop_tracing_ptr = stop_tracing; +IP_AGENT_EXPORT_VAR tracepoint_bkpt_ptr_type + flush_trace_buffer_ptr = flush_trace_buffer; +IP_AGENT_EXPORT_VAR tracepoint_bkpt_ptr_type + about_to_request_buffer_space_ptr = about_to_request_buffer_space; EXTERN_C_POP #endif @@ -6238,6 +6281,7 @@ upload_fast_traceframes (void) struct breakpoint *about_to_request_buffer_space_bkpt; CORE_ADDR ipa_trace_buffer_lo; CORE_ADDR ipa_trace_buffer_hi; + CORE_ADDR addr_about_to_request_buffer_space; if (read_inferior_uinteger (ipa_sym_addrs.addr_traceframe_read_count, &ipa_traceframe_read_count_racy)) @@ -6260,9 +6304,17 @@ upload_fast_traceframes (void) if (ipa_traceframe_write_count_racy == ipa_traceframe_read_count_racy) return; + if (read_inferior_data_pointer + (ipa_sym_addrs.addr_about_to_request_buffer_space_ptr, + &addr_about_to_request_buffer_space)) + { + internal_error (__FILE__, __LINE__, + "Error reading variable" + "addr_about_to_request_buffer_space_ptr inn lib"); + } + about_to_request_buffer_space_bkpt - = set_breakpoint_at (ipa_sym_addrs.addr_about_to_request_buffer_space, - NULL); + = set_breakpoint_at (addr_about_to_request_buffer_space, NULL); if (read_inferior_uinteger (ipa_sym_addrs.addr_trace_buffer_ctrl_curr, &ipa_trace_buffer_ctrl_curr)) diff --git a/gdb/testsuite/gdb.trace/ftrace-flush-buffer.c b/gdb/testsuite/gdb.trace/ftrace-flush-buffer.c new file mode 100644 index 0000000..c115f00 --- /dev/null +++ b/gdb/testsuite/gdb.trace/ftrace-flush-buffer.c @@ -0,0 +1,42 @@ +/* This testcase is part of GDB, the GNU debugger. + + Copyright 2011-2016 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#include "trace-common.h" + +static void +begin (void) +{} + +static void +end (void) +{} + +int +main () +{ + int i = 0; + int table[1048576]; + + begin (); + for (i; i < 10; i++) + { + FAST_TRACEPOINT_LABEL(set_point); + } + + end (); + return 0; +} diff --git a/gdb/testsuite/gdb.trace/ftrace-flush-buffer.exp b/gdb/testsuite/gdb.trace/ftrace-flush-buffer.exp new file mode 100644 index 0000000..08fa26a --- /dev/null +++ b/gdb/testsuite/gdb.trace/ftrace-flush-buffer.exp @@ -0,0 +1,98 @@ +# Copyright 2011-2016 Free Software Foundation, Inc. +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# The IPA flushes its internal buffer to GDBServer as it reaches 5MB +# (hardcoded). This test checks that this does not crash the inferiror by +# collecting 10MB of data. + +load_lib "trace-support.exp" + +standard_testfile +set executable $testfile +set expfile $testfile.exp + +# Some targets have leading underscores on assembly symbols. +set additional_flags [gdb_target_symbol_prefix_flags] + +if [prepare_for_testing $expfile $executable $srcfile \ + [list debug $additional_flags]] { + untested "failed to prepare for trace tests" + return -1 +} + +if ![runto_main] { + fail "Can't run to main to check for trace support" + return -1 +} + +if ![gdb_target_supports_trace] { + unsupported "target does not support trace" + return -1 +} + +if {![gdb_target_supports_fast_trace]} { + unsupported "Target does not support fast tracepoints." + return -1 +} + +set libipa [get_in_proc_agent] +set remote_libipa [gdb_load_shlib $libipa] + +# Can't use prepare_for_testing, because that splits compiling into +# building objects and then linking, and we'd fail with "linker input +# file unused because linking not done" when building the object. + +if { [gdb_compile "$srcdir/$subdir/$srcfile" $binfile \ + executable [list debug $additional_flags shlib=$libipa] ] != "" } { + untested "failed to compile ftrace tests" + return -1 +} +clean_restart ${executable} + +if ![runto_main] { + fail "Can't run to main for ftrace tests" + return 0 +} + +gdb_reinitialize_dir $srcdir/$subdir + +if { [gdb_test "info sharedlibrary" ".*${remote_libipa}.*" "IPA loaded"] != 0 } { + untested "Could not find IPA lib loaded" + return 1 +} + +gdb_test "break begin" ".*" "" + +gdb_test "break end" ".*" "" + +gdb_test "ftrace set_point" "Fast tracepoint .*" \ + "fast tracepoint at set_point" + +gdb_trace_setactions "collect at set_point: define actions" \ + "" \ + "collect table" "^$" + +gdb_test "continue" \ + ".*Breakpoint \[0-9\]+, begin .*" \ + "advance to trace begin" + +gdb_test_no_output "tstart" "start trace experiment" + +gdb_test "continue" \ + ".*Breakpoint \[0-9\]+, end .*" \ + "advance through tracing" + +gdb_test "tstatus" ".*Trace .*" "check on trace status" + +gdb_test "tstop" "" ""