From bfccc43c1218b6d89bb021381276ac742e7a9a9e Mon Sep 17 00:00:00 2001 From: Yao Qi Date: Fri, 18 Nov 2011 01:21:35 +0000 Subject: [PATCH] gdb/ * breakpoint.c (create_breakpoint): Produce query message according to breakpoint's type. Allocate tracepoint per correct type. Don't check SALs for pending fast tracepoints. * tracepoint.c (process_tracepoint_on_disconnect): New. (disconnect_tracing): Call process_tracepoint_on_disconnect. gdb/doc/ * gdb.texinfo (Create and Delete Tracepoints): Mention pending tracepoint. gdb/testsuite/ * gdb.trace/pending.exp: New. * gdb.trace/pending.c: New. * gdb.trace/pendshr1.c: New. * gdb.trace/pendshr2.c: New. * gdb.trace/change-loc.exp (tracepoint_change_loc_1): Check one tracepoint location becomes pending. (tracepoint_change_loc_2): New. --- gdb/ChangeLog | 9 + gdb/breakpoint.c | 28 +- gdb/doc/ChangeLog | 5 + gdb/doc/gdb.texinfo | 10 +- gdb/testsuite/ChangeLog | 10 + gdb/testsuite/gdb.trace/change-loc.exp | 129 +++++++- gdb/testsuite/gdb.trace/pending.c | 50 ++++ gdb/testsuite/gdb.trace/pending.exp | 525 +++++++++++++++++++++++++++++++++ gdb/testsuite/gdb.trace/pendshr1.c | 43 +++ gdb/testsuite/gdb.trace/pendshr2.c | 40 +++ gdb/tracepoint.c | 44 +++ 11 files changed, 875 insertions(+), 18 deletions(-) create mode 100644 gdb/testsuite/gdb.trace/pending.c create mode 100644 gdb/testsuite/gdb.trace/pending.exp create mode 100644 gdb/testsuite/gdb.trace/pendshr1.c create mode 100644 gdb/testsuite/gdb.trace/pendshr2.c diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 722eb20..393cdf0 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,5 +1,14 @@ 2011-11-18 Yao Qi + * breakpoint.c (create_breakpoint): Produce query message according to + breakpoint's type. + Allocate tracepoint per correct type. + Don't check SALs for pending fast tracepoints. + * tracepoint.c (process_tracepoint_on_disconnect): New. + (disconnect_tracing): Call process_tracepoint_on_disconnect. + +2011-11-18 Yao Qi + * breakpoint.c (install_breakpoint): Add one more parameter so that update_global_location_list is called conditionally. (create_fork_vfork_event_catchpoint): Update. diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c index 2554337..dc891c0 100644 --- a/gdb/breakpoint.c +++ b/gdb/breakpoint.c @@ -7836,8 +7836,8 @@ create_breakpoint (struct gdbarch *gdbarch, /* If pending breakpoint support is auto query and the user selects no, then simply return the error code. */ if (pending_break_support == AUTO_BOOLEAN_AUTO - && !nquery (_("Make breakpoint pending on " - "future shared library load? "))) + && !nquery (_("Make %s pending on future shared library load? "), + bptype_string (type_wanted))) return 0; /* At this point, either the user was queried about setting @@ -7894,7 +7894,7 @@ create_breakpoint (struct gdbarch *gdbarch, breakpoint_sals_to_pc (&sals); /* Fast tracepoints may have additional restrictions on location. */ - if (type_wanted == bp_fast_tracepoint) + if (!pending && type_wanted == bp_fast_tracepoint) check_fast_tracepoint_sals (gdbarch, &sals); /* Verify that condition can be parsed, before setting any @@ -7981,9 +7981,18 @@ create_breakpoint (struct gdbarch *gdbarch, make_cleanup (xfree, copy_arg); - b = set_raw_breakpoint_without_location (gdbarch, type_wanted, ops); - set_breakpoint_number (internal, b); - b->thread = -1; + if (is_tracepoint_type (type_wanted)) + { + struct tracepoint *t; + + t = XCNEW (struct tracepoint); + b = &t->base; + } + else + b = XNEW (struct breakpoint); + + init_raw_breakpoint_without_location (b, gdbarch, type_wanted, ops); + b->addr_string = canonical.canonical[0]; b->cond_string = NULL; b->ignore_count = ignore_count; @@ -7991,18 +8000,13 @@ create_breakpoint (struct gdbarch *gdbarch, b->condition_not_parsed = 1; b->enable_state = enabled ? bp_enabled : bp_disabled; b->pspace = current_program_space; - b->py_bp_object = NULL; if (enabled && b->pspace->executing_startup && (b->type == bp_breakpoint || b->type == bp_hardware_breakpoint)) b->enable_state = bp_startup_disabled; - if (!internal) - /* Do not mention breakpoints with a negative number, - but do notify observers. */ - mention (b); - observer_notify_breakpoint_created (b); + install_breakpoint (internal, b, 0); } if (sals.nelts > 1) diff --git a/gdb/doc/ChangeLog b/gdb/doc/ChangeLog index 4975cd2..e8d634a 100644 --- a/gdb/doc/ChangeLog +++ b/gdb/doc/ChangeLog @@ -1,3 +1,8 @@ +2011-11-18 Yao Qi + + * gdb.texinfo (Create and Delete Tracepoints): Mention pending + tracepoint. + 2011-11-15 Doug Evans * gdb.texinfo (Files): Document basenames-may-differ. diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo index f4f7f1e..bb9bede 100644 --- a/gdb/doc/gdb.texinfo +++ b/gdb/doc/gdb.texinfo @@ -10340,7 +10340,15 @@ in tracing}). If remote stub doesn't support the @samp{InstallInTrace} feature, all these changes don't take effect until the next @code{tstart} command, and once a trace experiment is running, further changes will -not have any effect until the next trace experiment starts. +not have any effect until the next trace experiment starts. In addition, +@value{GDBN} supports @dfn{pending tracepoints}---tracepoints whose +address is not yet resolved. (This is similar to pending breakpoints.) +Pending tracepoints are not downloaded to the target and not installed +until they are resolved. The resolution of pending tracepoints requires +@value{GDBN} support---when debugging with the remote target, and +@value{GDBN} disconnects from the remote stub (@pxref{disconnected +tracing}), pending tracepoints can not be resolved (and downloaded to +the remote stub) while @value{GDBN} is disconnected. Here are some examples of using the @code{trace} command: diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog index 2fdf03e..86aecc2 100644 --- a/gdb/testsuite/ChangeLog +++ b/gdb/testsuite/ChangeLog @@ -1,3 +1,13 @@ +2011-11-18 Yao Qi + + * gdb.trace/pending.exp: New. + * gdb.trace/pending.c: New. + * gdb.trace/pendshr1.c: New. + * gdb.trace/pendshr2.c: New. + * gdb.trace/change-loc.exp (tracepoint_change_loc_1): Check one + tracepoint location becomes pending. + (tracepoint_change_loc_2): New. + 2011-11-16 David S. Miller * lib/gdb.exp (can_single_step_to_signal_handler): Return zero when diff --git a/gdb/testsuite/gdb.trace/change-loc.exp b/gdb/testsuite/gdb.trace/change-loc.exp index e125024..d01f71c 100644 --- a/gdb/testsuite/gdb.trace/change-loc.exp +++ b/gdb/testsuite/gdb.trace/change-loc.exp @@ -118,27 +118,145 @@ proc tracepoint_change_loc_1 { trace_type } { \[0-9\]+\[\t \]+\(|fast \)tracepoint\[ \]+keep y.*\.*4\.1.* in func4.*4\.2.* in func4.*" \ "tracepoint with two locations" - setup_kfail "gdb/13392" x86_64-*-* - gdb_test "continue" ".*Breakpoint.*marker.*at.*$srcfile.*" \ - "continue to marker 2" - + gdb_test_multiple "continue" "continue to marker 2" { + -re ".*Breakpoint.*marker.*at.*$srcfile.*$gdb_prompt $" { + pass "continue to marker 2" + } + -re ".*$gdb_prompt $" { + kfail "gdb/13392" "continue to marker 2" + set pf_prefix $old_pf_prefix + return + } + } # tracepoint has three locations after shlib change-loc-2 is loaded. gdb_test "info trace" \ "Num Type\[ \]+Disp Enb Address\[ \]+What.* \[0-9\]+\[\t \]+\(|fast \)tracepoint\[ \]+keep y.*\.*4\.1.* in func4.*4\.2.* in func4.*4\.3.* in func4 .*" \ "tracepoint with three locations" + gdb_test "continue" ".*Breakpoint.*marker.*at.*$srcfile.*" \ + "continue to marker 3" + + # shlib is unloaded, there are still three locations, but one is pending. + gdb_test "info trace" \ + "Num Type\[ \]+Disp Enb Address\[ \]+What.* +\[0-9\]+\[\t \]+\(|fast \)tracepoint\[ \]+keep y.*\.*4\.1.* in func4.*4\.2.* in func4.*4\.3.* \\[\t \]+set_tracepoint.*" \ + "tracepoint with two locations (unload)" + gdb_test_no_output "tstop" - setup_kfail "gdb/13392" x86_64-*-* gdb_test "tfind" "Found trace frame 0, tracepoint 4.*" "tfind frame 0" gdb_test "tfind" "Target failed to find requested trace frame\\..*" set pf_prefix $old_pf_prefix } +# Set pending tracepoint. + +proc tracepoint_change_loc_2 { trace_type } { + global srcdir + global srcfile + global subdir + global pcreg + global binfile + global gdb_prompt + global pf_prefix + + set old_pf_prefix $pf_prefix + set pf_prefix "$pf_prefix 2 $trace_type:" + + gdb_exit + gdb_start + gdb_reinitialize_dir $srcdir/$subdir + + gdb_test_multiple "${trace_type} set_tracepoint" "set pending tracepoint" { + -re ".*Make \(|fast \)tracepoint pending.*y or \\\[n\\\]. $" { + gdb_test "y" "\(Fast t|T\)racepoint.*set_tracepoint.*pending." "set pending tracepoint" + } + } + + gdb_trace_setactions "set action for tracepoint" "" \ + "collect \$$pcreg" "^$" + + # tracepoint has no location information now. + gdb_test "info trace" \ + "Num Type\[ \]+Disp Enb Address\[ \]+What.* +\[0-9\]+\[\t \]+\(|fast \)tracepoint\[ \]+keep y.*PENDING.*set_tracepoint.*" \ + "single pending tracepoint info (without symbols)" + + gdb_load ${binfile} + # tracepoint has one location after executable is loaded. + gdb_test "info trace" \ + "Num Type\[ \]+Disp Enb Address\[ \]+What.* +\[0-9\]+\[\t \]+\(|fast \)tracepoint\[ \]+keep y.*func4.*" \ + "tracepoint with one location" + + set main_bp 0 + gdb_test_multiple "break main" "set breakpoint on main" { + -re "Breakpoint (\[0-9\]*) at .*, line.*$gdb_prompt $" { + set main_bp $expect_out(1,string) + } + } + gdb_run_cmd + + gdb_test "" \ + ".*Breakpoint.*main.*at.*$srcfile.*" \ + "run to main" + gdb_test_no_output "delete break $main_bp" + + # tracepoint has two locations after shlib change-loc-1 is loaded. + gdb_test "info trace" \ + "Num Type\[ \]+Disp Enb Address\[ \]+What.* +\[0-9\]+\[\t \]+\(|fast \)tracepoint\[ \]+keep y.*\.*1\.1.* in func4.*1\.2.* in func4.*" \ + "tracepoint with two locations" + + gdb_test "break marker" "Breakpoint.*at.* file .*$srcfile, line.*" \ + "breakpoint on marker" + + # tracepoint with two locations will be downloaded and installed. + gdb_test_no_output "tstart" + + gdb_test_multiple "continue" "continue to marker 1" { + -re ".*Breakpoint.*marker.*at.*$srcfile.*$gdb_prompt $" { + pass "continue to marker 1" + } + -re ".*$gdb_prompt $" { + kfail "gdb/13392" "continue to marker 1" + set pf_prefix $old_pf_prefix + return + } + } + + gdb_test "continue" ".*Breakpoint.*marker.*at.*$srcfile.*" \ + "continue to marker 2" + + # tracepoint has three locations after shlib change-loc-2 is loaded. + gdb_test "info trace" \ + "Num Type\[ \]+Disp Enb Address\[ \]+What.* +\[0-9\]+\[\t \]+\(|fast \)tracepoint\[ \]+keep y.*\.*1\.1.* in func4.*1\.2.* in func4.*1\.3.* in func4 .*" \ + "tracepoint with three locations" + + gdb_test "continue" ".*Breakpoint.*marker.*at.*$srcfile.*" \ + "continue to marker 3" + + # shlib is unloaded, there are still three locations, but one is pending. + gdb_test "info trace" \ + "Num Type\[ \]+Disp Enb Address\[ \]+What.* +\[0-9\]+\[\t \]+\(|fast \)tracepoint\[ \]+keep y.*\.*1\.1.* in func4.*1\.2.* in func4.*1\.3.* \\[\t \]+set_tracepoint.*" \ + "tracepoint with two locations (unload)" + + gdb_test_no_output "tstop" + + gdb_test "tfind" "Found trace frame 0, tracepoint 1.*" "tfind frame 0" + gdb_test "tfind" "Found trace frame 1, tracepoint 1.*" "tfind frame 1" + gdb_test "tfind" "Found trace frame 2, tracepoint 1.*" "tfind frame 2" + gdb_test "tfind" "Target failed to find requested trace frame\\..*" + + set pf_prefix $old_pf_prefix +} tracepoint_change_loc_1 "trace" +tracepoint_change_loc_2 "trace" # Re-compile test case with IPA. set libipa $objdir/../gdbserver/libinproctrace.so @@ -151,3 +269,4 @@ if { [gdb_compile "$srcdir/$subdir/$srcfile" $binfile executable \ } tracepoint_change_loc_1 "ftrace" +tracepoint_change_loc_2 "ftrace" diff --git a/gdb/testsuite/gdb.trace/pending.c b/gdb/testsuite/gdb.trace/pending.c new file mode 100644 index 0000000..08c751b --- /dev/null +++ b/gdb/testsuite/gdb.trace/pending.c @@ -0,0 +1,50 @@ +/* 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 . */ + +#include +#include + +extern void pendfunc (int x); + +static void +marker () {} + +int main() +{ + const char *libname = "pendshr2.sl"; + void *h; + int (*p_func) (int); + + pendfunc (3); + pendfunc (4); + pendfunc (3); + + marker (); + + h = dlopen (libname, RTLD_LAZY); + if (h == NULL) return 1; + + p_func = dlsym (h, "pendfunc2"); + if (p_func == NULL) return 2; + + (*p_func) (4); + + marker (); + + dlclose (h); + return 0; +} diff --git a/gdb/testsuite/gdb.trace/pending.exp b/gdb/testsuite/gdb.trace/pending.exp new file mode 100644 index 0000000..5851f04 --- /dev/null +++ b/gdb/testsuite/gdb.trace/pending.exp @@ -0,0 +1,525 @@ +# 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"; + +if $tracelevel then { + strace $tracelevel +} + +if {[skip_shlib_tests]} { + return 0 +} + +set testfile "pending" +set libfile1 "pendshr1" +set libfile2 "pendshr2" +set executable $testfile +set srcfile $testfile.c +set libsrc1 $srcdir/$subdir/$libfile1.c +set libsrc2 $srcdir/$subdir/$libfile2.c +set binfile $objdir/$subdir/$testfile +set lib_sl1 $objdir/$subdir/$libfile1.sl +set lib_sl2 $objdir/$subdir/$libfile2.sl + +set lib_opts [gdb_target_symbol_prefix_flags] + +if { [gdb_compile_shlib $libsrc1 $lib_sl1 $lib_opts] != "" + || [gdb_compile_shlib $libsrc2 $lib_sl2 $lib_opts] != ""} { + untested "Could not compile either $libsrc1 or $libsrc2" + return -1 +} + +set exec_opts [list debug shlib=$lib_sl1 shlib_load] +if { [gdb_compile $srcdir/$subdir/$srcfile $binfile executable $exec_opts] != "" } { + untested "Failed to compile $srcfile" + return -1 +} + +clean_restart $executable + +gdb_load_shlibs $lib_sl1 +gdb_load_shlibs $lib_sl2 + +if ![runto_main] { + fail "Can't run to main to check for trace support" + return -1 +} + +if ![gdb_target_supports_trace] { + unsupported "Current target does not support trace" + return -1; +} + +# Verify pending tracepoint is resolved to running to main. + +proc pending_tracepoint_resolved { trace_type } { + global srcdir + global subdir + global binfile + global srcfile + global lib_sl1 + global pf_prefix + + set old_pf_prefix $pf_prefix + lappend pf_prefix "$trace_type" "resolved:" + + # Start with a fresh gdb. + gdb_exit + gdb_start + gdb_reinitialize_dir $srcdir/$subdir + + gdb_test_multiple "$trace_type set_point1" "set pending tracepoint" { + -re ".*Make \(fast |\)tracepoint pending.*y or \\\[n\\\]. $" { + gdb_test "y" "\(Fast t|T\)racepoint.*set_point1.*pending." \ + "set pending tracepoint (without symbols)" + } + } + + gdb_test "info trace" \ + "Num Type\[ \]+Disp Enb Address\[ \]+What.* +\[0-9\]+\[\t \]+\(fast |\)tracepoint\[ \]+keep y.*PENDING.*set_point1.*" \ + "single pending tracepoint info (without symbols)" + + gdb_load ${binfile} + + gdb_test "break main" "Breakpoint.*at.* file .*$srcfile, line.*" \ + "breakpoint function" + + gdb_run_cmd + gdb_test "" "Breakpoint 2, main.*" + + # Run to main which should resolve a pending tracepoint + gdb_test "info trace" \ + "Num Type\[ \]+Disp Enb Address\[ \]+What.* +\[0-9\]+\[\t \]+\(fast |\)tracepoint\[ \]+keep y.*pendfunc.*" \ + "single tracepoint info" + + set pf_prefix $old_pf_prefix +} + +# Verify pending tracepoint is resolved and works as expected. + +proc pending_tracepoint_works { trace_type } { + global executable + global srcfile + global lib_sl1 + global pf_prefix + global gdb_prompt + + set old_pf_prefix $pf_prefix + lappend pf_prefix "$trace_type" "works:" + + # Restart with a fresh gdb. + clean_restart $executable + + # Test setting and querying pending tracepoints + + gdb_test_multiple "$trace_type set_point1" "set pending tracepoint" { + -re ".*Make \(fast |\)tracepoint pending.*y or \\\[n\\\]. $" { + gdb_test "y" "\(Fast t|T\)racepoint.*set_point1.*pending." "set pending tracepoint" + } + } + + gdb_test "info trace" \ + "Num Type\[ \]+Disp Enb Address\[ \]+What.* +\[0-9\]+\[\t \]+\(fast |\)tracepoint\[ \]+keep y.*PENDING.*set_point1.*" \ + "single pending tracepoint info" + + # Run to main which should resolve a pending tracepoint + gdb_test "break main" "Breakpoint.*at.* file .*$srcfile, line.*" \ + "breakpoint function" + gdb_run_cmd + gdb_test "" "Breakpoint 2, main.*" + + gdb_test "break marker" "Breakpoint.*at.* file .*$srcfile, line.*" \ + "breakpoint on marker" + + gdb_test_no_output "tstart" "start trace experiment" + + gdb_test_multiple "continue" "continue to marker" { + -re "Continuing.\r\n\r\nBreakpoint.*marker.*at.*$srcfile.*$gdb_prompt $" { + pass "continue to marker" + } + -re ".*$gdb_prompt $" { + kfail "gdb/13392" "continue to marker" + set pf_prefix $old_pf_prefix + return + } + } + + gdb_test "tstop" "\[\r\n\]+" "stop trace experiment" + + gdb_test "tfind start" "#0 .*" "tfind test frame 0" + gdb_test "tfind" "Found trace frame 1, tracepoint 1.*" "tfind test frame 1" + gdb_test "tfind" "Found trace frame 2, tracepoint 1.*" "tfind test frame 2" + gdb_test "tfind" "Target failed to find requested trace frame..*" "tfind test frame" + + set pf_prefix $old_pf_prefix +} + +# Verify pending tracepoint is resolved during trace. + +proc pending_tracepoint_resolved_during_trace { trace_type } { + global executable + global srcfile + global gdb_prompt + global lib_sl1 + global pf_prefix + + set old_pf_prefix $pf_prefix + lappend pf_prefix "$trace_type" "resolved_in_trace:" + + # 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_multiple "$trace_type set_point2" "set pending tracepoint on set_point2" { + -re ".*Make \(fast |\)tracepoint pending.*y or \\\[n\\\]. $" { + gdb_test "y" "\(Fast t|T\)racepoint.*set_point2.*pending." \ + "set pending tracepoint (without symbols)" + } + } + + gdb_test "info trace" \ + "Num Type\[ \]+Disp Enb Address\[ \]+What.* +\[0-9\]+\[\t \]+\(fast |\)tracepoint\[ \]+keep y.*PENDING.*set_point2.*" \ + "single pending tracepoint on set_point2" + + gdb_test "break marker" "Breakpoint.*at.* file .*$srcfile, line.*" \ + "breakpoint on marker" + + gdb_test_no_output "tstart" "start trace experiment" + + gdb_test "continue" "Continuing.\r\n\r\nBreakpoint.*marker.*at.*pending.c.*" \ + "continue to marker 1" + + gdb_test_multiple "continue" "continue to marker 2" { + -re "Continuing.\r\n\r\nBreakpoint.*marker.*at.*$srcfile.*$gdb_prompt $" { + pass "continue to marker 2" + } + -re ".*$gdb_prompt $" { + kfail "gdb/13392" "continue to marker 2" + set pf_prefix $old_pf_prefix + return + } + } + + gdb_test "tstop" "\[\r\n\]+" "stop trace experiment" + + # tracepoint should be resolved. + gdb_test "info trace" \ + "Num Type\[ \]+Disp Enb Address\[ \]+What.* +\[0-9\]+\[\t \]+\(fast |\)tracepoint\[ \]+keep y.*pendfunc2.*" \ + "tracepoint is resolved" + + gdb_test "tfind start" "#0 .*" "tfind test frame 0" + gdb_test "tfind" "Target failed to find requested trace frame..*" "tfind test frame" + + set pf_prefix $old_pf_prefix +} + +# Verify pending tracepoint is resolved and installed during trace. + +proc pending_tracepoint_installed_during_trace { trace_type } { + global executable + global srcfile + global lib_sl1 + global gdb_prompt + global pf_prefix + global hex + + set old_pf_prefix $pf_prefix + lappend pf_prefix "$trace_type" "installed_in_trace:" + + # 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 "next" ".*" + gdb_test "trace main" "Tracepoint \[0-9\] at .*" "set tracepoint on main" + + gdb_test "break marker" "Breakpoint.*at.* file .*$srcfile, line.*" \ + "breakpoint on marker" + + gdb_test_no_output "tstart" "start trace experiment" + + gdb_test "continue" "Continuing.\r\n\r\nBreakpoint.*marker.*at.*${srcfile}.*" \ + "continue to marker 1" + + # Set a pending tracepoint during a tracing experiment. + gdb_test_multiple "$trace_type set_point2" "set pending tracepoint on set_point2" { + -re ".*Make \(fast |\)tracepoint pending.*y or \\\[n\\\]. $" { + gdb_test "y" "\(Fast t|T\)racepoint.*set_point2.*pending." \ + "set pending tracepoint" + } + } + + gdb_test "info trace" \ + "Num Type\[ \]+Disp Enb Address\[ \]+What.* +\[0-9\]+\[\t \]+\(fast |\)tracepoint\[ \t\]+keep y.*PENDING.*set_point2.*" \ + "single pending tracepoint on set_point2" + + gdb_test_multiple "continue" "continue to marker 2" { + -re "Continuing.\r\n\r\nBreakpoint.*marker.*at.*$srcfile.*$gdb_prompt $" { + pass "continue to marker 2" + } + -re ".*$gdb_prompt $" { + kfail "gdb/13392" "continue to marker 2" + set pf_prefix $old_pf_prefix + return + } + } + + gdb_test "tstop" "\[\r\n\]+" "stop trace experiment" + + # tracepoint should be resolved. + gdb_test "info trace" \ + "Num Type\[ \]+Disp Enb Address\[ \]+What.* +\[0-9\]+\[\t \]+\(fast |\)tracepoint\[ \]+keep y.*pendfunc2.*" \ + "tracepoint is resolved" + + gdb_test "tfind start" "#0 $hex in pendfunc2 .*" "tfind test frame 0" + gdb_test "tfind" "Target failed to find requested trace frame..*" "tfind test frame" + + set pf_prefix $old_pf_prefix +} + + +# Verify pending tracepoint will no longer work if we disconnect during tracing. + +proc pending_tracepoint_disconnect_during_trace { trace_type } { + global executable + global srcfile + global lib_sl1 + global pf_prefix + global gdb_prompt + + set old_pf_prefix $pf_prefix + lappend pf_prefix "$trace_type" "disconn:" + + # 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_multiple "trace pendfunc3" "set pending tracepoint on set_point2" { + -re ".*Make \(fast |\)tracepoint pending.*y or \\\[n\\\]. $" { + gdb_test "y" "\(Fast t|T\)racepoint.*pendfunc3.*pending." \ + "set pending tracepoint on pendfun3" + } + } + + gdb_test "break marker" "Breakpoint.*at.* file .*$srcfile, line.*" \ + "breakpoint on marker" + + gdb_test_no_output "tstart" "start trace experiment" + + gdb_test "continue" "Continuing.\r\n\r\nBreakpoint.*marker.*at.*pending.c.*" \ + "continue to marker" + + set test "disconnect with pending tracepoint" + gdb_test_multiple "disconnect" $test { + -re "warning: Pending tracepoints will not be resolved while GDB is disconnected.*Trace is running but will stop on detach; detach anyway\\? \\(y or n\\) $" { + pass $test + + set test "disconnected" + gdb_test_multiple "y" $test { + -re "$gdb_prompt $" { + pass "$test" + } + } + } + } + + set pf_prefix $old_pf_prefix +} + + +# Verify disconnect after pending tracepoint has been resolved. + +proc pending_tracepoint_disconnect_after_resolved { trace_type } { + global executable + global srcfile + global lib_sl1 + global gdb_prompt + global pf_prefix + + set old_pf_prefix $pf_prefix + lappend pf_prefix "$trace_type" "disconn_resolved:" + + # 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_multiple "trace set_point2" "set pending tracepoint on set_point2" { + -re ".*Make \(fast |\)tracepoint pending.*y or \\\[n\\\]. $" { + gdb_test "y" "\(Fast t|T\)racepoint.*set_point2.*pending." \ + "set pending tracepoint on pendfun2" + } + } + + gdb_test "break marker" "Breakpoint.*at.* file .*$srcfile, line.*" \ + "breakpoint on marker" + + gdb_test_no_output "tstart" "start trace experiment" + + gdb_test "continue" "Continuing.\r\n\r\nBreakpoint.*marker.*at.*pending.c.*" \ + "continue to marker 1" + gdb_test "continue" "Continuing.\r\n\r\nBreakpoint.*marker.*at.*pending.c.*" \ + "continue to marker 2" + + # There should be no pending tracepoint, so no warning should be emitted. + set test "disconnect with resolved tracepoint" + gdb_test_multiple "disconnect" $test { + -re "warning: Pending tracepoints will not be resolved while GDB is disconnected.*Trace is running but will stop on detach; detach anyway\\? \\(y or n\\) $" { + fail $test + } + -re "Trace is running but will stop on detach; detach anyway\\? \\(y or n\\) $" { + pass $test + } + } + set test "disconnected" + gdb_test_multiple "y" $test { + -re "$gdb_prompt $" { + pass "$test" + } + } + + set pf_prefix $old_pf_prefix +} + +# Verify action works properly in resolved tracepoint. + +proc pending_tracepoint_with_action_resolved { trace_type } { + global executable + global srcfile + global lib_sl1 + global gdb_prompt + global pf_prefix + + set old_pf_prefix $pf_prefix + lappend pf_prefix "$trace_type" "action_resolved:" + + # 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_multiple "$trace_type set_point2" "set pending tracepoint on set_point2" { + -re ".*Make \(fast |\)tracepoint pending.*y or \\\[n\\\]. $" { + gdb_test "y" "\(Fast t|T\)racepoint.*set_point2.*pending." \ + "set pending tracepoint (without symbols)" + } + } + + set pcreg "pc" + if [is_amd64_regs_target] { + set pcreg "rip" + } elseif [is_x86_like_target] { + set pcreg "eip" + } + + gdb_trace_setactions "set action for pending tracepoint" "" \ + "collect \$$pcreg" "^$" + + gdb_test "info trace" \ + "Num Type\[ \]+Disp Enb Address\[ \]+What.* +\[0-9\]+\[\t \]+\(fast |\)tracepoint\[ \]+keep y.*PENDING.*set_point2.*" \ + "single pending tracepoint on set_point2" + + gdb_test "break marker" "Breakpoint.*at.* file .*$srcfile, line.*" \ + "breakpoint on marker" + + gdb_test_no_output "tstart" "start trace experiment" + + gdb_test "continue" "Continuing.\r\n\r\nBreakpoint.*marker.*at.*pending.c.*" \ + "continue to marker 1" + + gdb_test_multiple "continue" "continue to marker 2" { + -re "Continuing.\r\n\r\nBreakpoint.*marker.*at.*$srcfile.*$gdb_prompt $" { + pass "continue to marker 2" + } + -re ".*$gdb_prompt $" { + kfail "gdb/13392" "continue to marker 2" + set pf_prefix $old_pf_prefix + return + } + } + + gdb_test "tstop" "\[\r\n\]+" "stop trace experiment" + + # tracepoint should be resolved. + gdb_test "info trace" \ + "Num Type\[ \]+Disp Enb Address\[ \]+What.* +\[0-9\]+\[\t \]+\(fast |\)tracepoint\[ \]+keep y.*pendfunc2.*" \ + "tracepoint is resolved" + + gdb_test "tfind start" "#0 .*" "tfind test frame 0" + gdb_test "tdump" "Data collected at tracepoint .*, trace frame \[0-9\]:.*\\$${pcreg} = .*" + gdb_test "tfind" "Target failed to find requested trace frame..*" "tfind test frame" + + set pf_prefix $old_pf_prefix +} + +pending_tracepoint_resolved "trace" + +pending_tracepoint_works "trace" + +pending_tracepoint_resolved_during_trace "trace" + +pending_tracepoint_disconnect_during_trace "trace" + +pending_tracepoint_disconnect_after_resolved "trace" + +pending_tracepoint_with_action_resolved "trace" + +pending_tracepoint_installed_during_trace "trace" + +# Re-compile test case with IPA. +set libipa $objdir/../gdbserver/libinproctrace.so +gdb_load_shlibs $libipa + +lappend exec_opts "shlib=$libipa" + +if { [gdb_compile $srcdir/$subdir/$srcfile $binfile executable $exec_opts] != "" } { + untested "Failed to compile $srcfile" + return -1 +} + +pending_tracepoint_resolved "ftrace" +pending_tracepoint_works "ftrace" +pending_tracepoint_resolved_during_trace "ftrace" +pending_tracepoint_disconnect_during_trace "ftrace" +pending_tracepoint_disconnect_after_resolved "ftrace" +pending_tracepoint_with_action_resolved "ftrace" +pending_tracepoint_installed_during_trace "ftrace" diff --git a/gdb/testsuite/gdb.trace/pendshr1.c b/gdb/testsuite/gdb.trace/pendshr1.c new file mode 100644 index 0000000..f2826c6 --- /dev/null +++ b/gdb/testsuite/gdb.trace/pendshr1.c @@ -0,0 +1,43 @@ +/* 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 + +static void +pendfunc1 (void) +{ + int x = 0; + int y = x + 4; +} + +void +pendfunc (int x) +{ + /* `set_point1' 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_point1) "\n" + SYMBOL(set_point1) ":\n" +#if (defined __x86_64__ || defined __i386__) + " call " SYMBOL(pendfunc1) "\n" +#endif + ); +} diff --git a/gdb/testsuite/gdb.trace/pendshr2.c b/gdb/testsuite/gdb.trace/pendshr2.c new file mode 100644 index 0000000..46eedee --- /dev/null +++ b/gdb/testsuite/gdb.trace/pendshr2.c @@ -0,0 +1,40 @@ +/* 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 + +static void +foo () +{} + +void +pendfunc2 (int x) +{ + /* `set_point2' 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_point2) "\n" + SYMBOL(set_point2) ":\n" +#if (defined __x86_64__ || defined __i386__) + " call " SYMBOL(foo) "\n" +#endif + ); +} diff --git a/gdb/tracepoint.c b/gdb/tracepoint.c index e155515..97ab633 100644 --- a/gdb/tracepoint.c +++ b/gdb/tracepoint.c @@ -1642,6 +1642,48 @@ add_aexpr (struct collection_list *collect, struct agent_expr *aexpr) collect->next_aexpr_elt++; } +static void +process_tracepoint_on_disconnect (void) +{ + VEC(breakpoint_p) *tp_vec = NULL; + int ix; + struct breakpoint *b; + int has_pending_p = 0; + + /* Check whether we still have pending tracepoint. If we have, warn the + user that pending tracepoint will no longer work. */ + tp_vec = all_tracepoints (); + for (ix = 0; VEC_iterate (breakpoint_p, tp_vec, ix, b); ix++) + { + if (b->loc == NULL) + { + has_pending_p = 1; + break; + } + else + { + struct bp_location *loc1; + + for (loc1 = b->loc; loc1; loc1 = loc1->next) + { + if (loc1->shlib_disabled) + { + has_pending_p = 1; + break; + } + } + + if (has_pending_p) + break; + } + } + VEC_free (breakpoint_p, tp_vec); + + if (has_pending_p) + warning (_("Pending tracepoints will not be resolved while" + " GDB is disconnected\n")); +} + void start_tracing (void) @@ -2020,6 +2062,8 @@ disconnect_tracing (int from_tty) disconnected-tracing. */ if (current_trace_status ()->running && from_tty) { + process_tracepoint_on_disconnect (); + if (current_trace_status ()->disconnected_tracing) { if (!query (_("Trace is running and will " -- 2.7.4