From b9fd179153353a88a34dd97a03ee698376212d29 Mon Sep 17 00:00:00 2001 From: Pedro Alves Date: Mon, 31 Oct 2011 12:55:26 +0000 Subject: [PATCH] 2011-10-31 Pedro Alves gdb/gdbserver/ * mem-break.c (check_mem_write): Add `myaddr' parameter. Don't clobber the breakpoints' shadows with fast tracepoint jumps. * mem-break.h (check_mem_write): Add `myaddr' parameter. * target.c (write_inferior_memory): Also pass MYADDR down to check_mem_write. gdb/testsuite/ * gdb.trace/trace-break.c: New. * gdb.trace/trace-break.exp: New. --- gdb/gdbserver/ChangeLog | 8 + gdb/gdbserver/mem-break.c | 7 +- gdb/gdbserver/mem-break.h | 6 +- gdb/gdbserver/target.c | 2 +- gdb/testsuite/ChangeLog | 6 + gdb/testsuite/gdb.trace/trace-break.c | 58 ++++++ gdb/testsuite/gdb.trace/trace-break.exp | 240 ++++++++++++++++++++++++ 7 files changed, 321 insertions(+), 6 deletions(-) create mode 100644 gdb/testsuite/gdb.trace/trace-break.c create mode 100644 gdb/testsuite/gdb.trace/trace-break.exp diff --git a/gdb/gdbserver/ChangeLog b/gdb/gdbserver/ChangeLog index eab3ac8b7d9..45d3f86dc71 100644 --- a/gdb/gdbserver/ChangeLog +++ b/gdb/gdbserver/ChangeLog @@ -1,3 +1,11 @@ +2011-10-31 Pedro Alves + + * mem-break.c (check_mem_write): Add `myaddr' parameter. Don't + clobber the breakpoints' shadows with fast tracepoint jumps. + * mem-break.h (check_mem_write): Add `myaddr' parameter. + * target.c (write_inferior_memory): Also pass MYADDR down to + check_mem_write. + 2011-10-07 Ulrich Weigand * configure.ac: Check support for personality routine. diff --git a/gdb/gdbserver/mem-break.c b/gdb/gdbserver/mem-break.c index eea8c713471..348f59d9672 100644 --- a/gdb/gdbserver/mem-break.c +++ b/gdb/gdbserver/mem-break.c @@ -1029,7 +1029,8 @@ check_mem_read (CORE_ADDR mem_addr, unsigned char *buf, int mem_len) } void -check_mem_write (CORE_ADDR mem_addr, unsigned char *buf, int mem_len) +check_mem_write (CORE_ADDR mem_addr, unsigned char *buf, + const unsigned char *myaddr, int mem_len) { struct process_info *proc = current_process (); struct raw_breakpoint *bp = proc->raw_breakpoints; @@ -1063,7 +1064,7 @@ check_mem_write (CORE_ADDR mem_addr, unsigned char *buf, int mem_len) buf_offset = start - mem_addr; memcpy (fast_tracepoint_jump_shadow (jp) + copy_offset, - buf + buf_offset, copy_len); + myaddr + buf_offset, copy_len); if (jp->inserted) memcpy (buf + buf_offset, fast_tracepoint_jump_insn (jp) + copy_offset, copy_len); @@ -1092,7 +1093,7 @@ check_mem_write (CORE_ADDR mem_addr, unsigned char *buf, int mem_len) copy_offset = start - bp->pc; buf_offset = start - mem_addr; - memcpy (bp->old_data + copy_offset, buf + buf_offset, copy_len); + memcpy (bp->old_data + copy_offset, myaddr + buf_offset, copy_len); if (bp->inserted) { if (validate_inserted_breakpoint (bp)) diff --git a/gdb/gdbserver/mem-break.h b/gdb/gdbserver/mem-break.h index 2f1dbeab7be..c5cb20cf22a 100644 --- a/gdb/gdbserver/mem-break.h +++ b/gdb/gdbserver/mem-break.h @@ -102,9 +102,11 @@ void check_mem_read (CORE_ADDR mem_addr, unsigned char *buf, int mem_len); /* See if any breakpoints shadow the target memory area from MEM_ADDR to MEM_ADDR + MEM_LEN. Update the data to be written to the target - (in BUF) if necessary, as well as the original data for any breakpoints. */ + (in BUF, a copy of MYADDR on entry) if necessary, as well as the + original data for any breakpoints. */ -void check_mem_write (CORE_ADDR mem_addr, unsigned char *buf, int mem_len); +void check_mem_write (CORE_ADDR mem_addr, + unsigned char *buf, const unsigned char *myaddr, int mem_len); /* Set the byte pattern to insert for memory breakpoints. This function must be called before any breakpoints are set. */ diff --git a/gdb/gdbserver/target.c b/gdb/gdbserver/target.c index 83eb27f4357..873ee68e107 100644 --- a/gdb/gdbserver/target.c +++ b/gdb/gdbserver/target.c @@ -63,7 +63,7 @@ write_inferior_memory (CORE_ADDR memaddr, const unsigned char *myaddr, buffer = xmalloc (len); memcpy (buffer, myaddr, len); - check_mem_write (memaddr, buffer, len); + check_mem_write (memaddr, buffer, myaddr, len); res = (*the_target->write_memory) (memaddr, buffer, len); free (buffer); buffer = NULL; diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog index 5a66e2c90a0..ceecad15907 100644 --- a/gdb/testsuite/ChangeLog +++ b/gdb/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2011-10-31 Yao Qi + Pedro Alves + + * gdb.trace/trace-break.c: New. + * gdb.trace/trace-break.exp: New. + 2011-10-28 Jan Kratochvil * gdb.threads/no-unwaited-for-left.exp: Specify $srcfile for diff --git a/gdb/testsuite/gdb.trace/trace-break.c b/gdb/testsuite/gdb.trace/trace-break.c new file mode 100644 index 00000000000..fd061424421 --- /dev/null +++ b/gdb/testsuite/gdb.trace/trace-break.c @@ -0,0 +1,58 @@ +/* This testcase is part of GDB, the GNU debugger. + + Copyright 2011 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 . */ + +#ifdef SYMBOL_PREFIX +#define SYMBOL(str) SYMBOL_PREFIX #str +#else +#define SYMBOL(str) #str +#endif + +/* Called from asm. */ +static void __attribute__((used)) +func (void) +{} + +static void +marker (void) +{ + /* Some code to make sure `b marker' and `b set_point' set + breakpoints at different addresses. */ + int a = 0; + int b = a; + + /* `set_point' is the label where we'll set multiple tracepoints and + breakpoints at. The insn at the label must the large enough to + fit a fast tracepoint jump. */ + asm (" .global " SYMBOL(set_point) "\n" + SYMBOL(set_point) ":\n" +#if (defined __x86_64__ || defined __i386__) + " call " SYMBOL(func) "\n" +#endif + ); +} + +static void +end (void) +{} + +int +main () +{ + marker (); + end (); + return 0; +} diff --git a/gdb/testsuite/gdb.trace/trace-break.exp b/gdb/testsuite/gdb.trace/trace-break.exp new file mode 100644 index 00000000000..4a14d32fe44 --- /dev/null +++ b/gdb/testsuite/gdb.trace/trace-break.exp @@ -0,0 +1,240 @@ +# Copyright 2011 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 . + +load_lib "trace-support.exp"; + +set testfile "trace-break" +set executable $testfile +set srcfile $testfile.c +set binfile $objdir/$subdir/$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; +} + +# Set breakpoint and tracepoint at the same address. + +proc break_trace_same_addr_1 { trace_type option } { + global executable + global pf_prefix + global hex + + set old_pf_prefix $pf_prefix + set pf_prefix "$pf_prefix 1 $trace_type $option:" + + # Start with a fresh gdb. + clean_restart ${executable} + if ![runto_main] { + fail "Can't run to main" + set pf_prefix $old_pf_prefix + return -1 + } + + gdb_test_no_output "set breakpoint always-inserted ${option}" + + gdb_test "break end" "Breakpoint \[0-9\] at $hex: file.*" + + gdb_test "break set_point" "Breakpoint \[0-9\] at $hex: file.*" + gdb_test "${trace_type} set_point" "\(Fast t|T\)racepoint \[0-9\] at $hex: file.*" + + gdb_test_no_output "tstart" + + gdb_test "continue" "Continuing\\.\[ \r\n\]+Breakpoint.*" "continue to set_point" + + gdb_test "continue" "Continuing\\.\[ \r\n\]+Breakpoint.*" "continue to end" + gdb_test_no_output "tstop" + + gdb_test "tfind" "Found trace frame 0, tracepoint .*" "tfind frame 0" + gdb_test "tfind" "Target failed to find requested trace frame\\..*" + + set pf_prefix $old_pf_prefix +} + +# Set multiple tracepoints at the same address. + +proc break_trace_same_addr_2 { trace_type1 trace_type2 option } { + global executable + global pf_prefix + global hex + + set old_pf_prefix $pf_prefix + set pf_prefix "$pf_prefix 2 $trace_type1 $trace_type2 $option:" + + # Start with a fresh gdb. + clean_restart ${executable} + if ![runto_main] { + fail "Can't run to main" + set pf_prefix $old_pf_prefix + return -1 + } + + gdb_test_no_output "set breakpoint always-inserted ${option}" + + gdb_test "break end" "Breakpoint \[0-9\] at $hex: file.*" + + gdb_test "${trace_type1} set_point" \ + "\(Fast t|T\)racepoint \[0-9\] at $hex: file.*" \ + "${trace_type1} set_point (1)" + + gdb_test "${trace_type2} set_point" \ + "\(Fast t|T\)racepoint \[0-9\] at $hex: file.*" \ + "${trace_type2} set_point (2)" + + gdb_test_no_output "tstart" + gdb_test "continue" "Continuing\\.\[ \r\n\]+Breakpoint.*" "continue to end" + + gdb_test_no_output "tstop" + + gdb_test "tfind" "Found trace frame 0, tracepoint .*" "tfind frame 0" + gdb_test "tfind" "Found trace frame 1, tracepoint .*" "tfind frame 1" + gdb_test "tfind" "Target failed to find requested trace frame\\..*" + + set pf_prefix $old_pf_prefix +} + +# Set breakpoint and tracepoint at the same address. Delete breakpoint, and verify +# that tracepoint still works. + +proc break_trace_same_addr_3 { trace_type option } { + global executable + global pf_prefix + global hex + + set old_pf_prefix $pf_prefix + set pf_prefix "$pf_prefix 3 $trace_type $option:" + + # Start with a fresh gdb. + clean_restart ${executable} + if ![runto_main] { + fail "Can't run to main" + set pf_prefix $old_pf_prefix + return -1 + } + + gdb_test_no_output "set breakpoint always-inserted ${option}" + gdb_test "break marker" "Breakpoint \[0-9\] at $hex: file.*" + gdb_test "break end" "Breakpoint \[0-9\] at $hex: file.*" + + gdb_test "break set_point" "Breakpoint \[0-9\] at $hex: file.*" + gdb_test "${trace_type} set_point" "\(Fast t|T\)racepoint \[0-9\] at $hex: file.*" + + gdb_test_no_output "tstart" + + gdb_test "continue" "Continuing\\.\[ \r\n\]+Breakpoint.*" "continue to marker" + gdb_test "delete break 4" + + gdb_test "continue" "Continuing\\.\[ \r\n\]+Breakpoint.*" "continue to end" + gdb_test_no_output "tstop" + + gdb_test "tfind" "Found trace frame 0, tracepoint .*" "tfind frame 0" + gdb_test "tfind" "Target failed to find requested trace frame\\..*" + + set pf_prefix $old_pf_prefix +} + +# Set breakpoint and tracepoint at the same address. Delete tracepoint, and verify +# that breakpoint still works. + +proc break_trace_same_addr_4 { trace_type option } { + global executable + global pf_prefix + global hex + + set old_pf_prefix $pf_prefix + set pf_prefix "$pf_prefix 4 $trace_type $option:" + + # Start with a fresh gdb. + clean_restart ${executable} + if ![runto_main] { + fail "Can't run to main" + set pf_prefix $old_pf_prefix + return -1 + } + + gdb_test_no_output "set breakpoint always-inserted ${option}" + gdb_test "break marker" "Breakpoint \[0-9\] at $hex: file.*" + gdb_test "break end" "Breakpoint \[0-9\] at $hex: file.*" + + gdb_test "break set_point" "Breakpoint \[0-9\] at $hex: file.*" + gdb_test "${trace_type} set_point" "\(Fast t|T\)racepoint \[0-9\] at $hex: file.*" + + gdb_test "continue" "Continuing\\.\[ \r\n\]+Breakpoint.*" "continue to marker" + # Delete tracepoint set on set_point. + gdb_test "delete trace 5" + + gdb_test "tstart" "No tracepoints defined, not starting trace.*" + + gdb_test "continue" "Continuing\\.\[ \r\n\]+Breakpoint.*" "continue to set_point" + gdb_test "continue" "Continuing\\.\[ \r\n\]+Breakpoint.*" "continue to end" + gdb_test "tstop" "Trace is not running.*" + + gdb_test "tfind" "Target failed to find requested trace frame\\..*" + + set pf_prefix $old_pf_prefix +} + +foreach break_always_inserted { "on" "off" } { + break_trace_same_addr_1 "trace" ${break_always_inserted} + break_trace_same_addr_2 "trace" "trace" ${break_always_inserted} + break_trace_same_addr_3 "trace" ${break_always_inserted} + break_trace_same_addr_4 "trace" ${break_always_inserted} +} + +set libipa $objdir/../gdbserver/libinproctrace.so +gdb_load_shlibs $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" ".*libinproctrace\.so.*" "IPA loaded"] != 0 } { + untested "Could not find IPA lib loaded" +} else { + foreach break_always_inserted { "on" "off" } { + break_trace_same_addr_1 "ftrace" ${break_always_inserted} + break_trace_same_addr_2 "trace" "ftrace" ${break_always_inserted} + break_trace_same_addr_2 "ftrace" "trace" ${break_always_inserted} + break_trace_same_addr_3 "ftrace" ${break_always_inserted} + break_trace_same_addr_4 "ftrace" ${break_always_inserted} + } +} -- 2.30.2