diff mbox

[v3,13/18] Export tracing control breakpoints functions via global function pointers

Message ID 1467726030-13020-14-git-send-email-antoine.tremblay@ericsson.com
State New
Headers show

Commit Message

Antoine Tremblay July 5, 2016, 1:40 p.m. UTC
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)<stop_tracing, flush_trace_buffer,
	about_to_request_buffer_space>: 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 mbox

Patch

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 <http://www.gnu.org/licenses/>.  */
+
+#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 <http://www.gnu.org/licenses/>.
+
+# 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" "" ""