| # 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/>. |
| |
| load_lib "trace-support.exp" |
| |
| if {[skip_shlib_tests]} { |
| return 0 |
| } |
| |
| standard_testfile |
| set libfile1 "pendshr1" |
| set libfile2 "pendshr2" |
| set executable $testfile |
| set libsrc1 $srcdir/$subdir/$libfile1.c |
| set libsrc2 $srcdir/$subdir/$libfile2.c |
| set lib_sl1 [standard_output_file $libfile1.sl] |
| set lib_sl2 [standard_output_file $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_shlib $lib_sl1 |
| gdb_load_shlib $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 } { |
| with_test_prefix "$trace_type resolved" { |
| global srcdir |
| global subdir |
| global binfile |
| global srcfile |
| global lib_sl1 |
| |
| # 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" |
| } |
| } |
| |
| # Verify pending tracepoint is resolved and works as expected. |
| |
| proc pending_tracepoint_works { trace_type } { |
| with_test_prefix "$trace_type works" { |
| global executable |
| global srcfile |
| global lib_sl1 |
| global gdb_prompt |
| |
| # 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" |
| |
| set test "start trace experiment" |
| gdb_test_multiple "tstart" $test { |
| -re "^tstart\r\n$gdb_prompt $" { |
| pass $test |
| } |
| -re "Target returns error code .* too far .*$gdb_prompt $" { |
| if [string equal $trace_type "ftrace"] { |
| # The target was unable to install the fast tracepoint |
| # (e.g., jump pad too far from tracepoint). |
| pass "$test (too far)" |
| # Skip the rest of the tests. |
| return |
| } else { |
| fail $test |
| } |
| } |
| |
| } |
| |
| gdb_test "continue" "Continuing.\r\n\r\n(Thread .* hit )?Breakpoint.*marker.*at.*$srcfile.*" \ |
| "continue to marker" |
| |
| 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" |
| } |
| } |
| |
| # Verify pending tracepoint is resolved during trace. |
| |
| proc pending_tracepoint_resolved_during_trace { trace_type } \ |
| { with_test_prefix "$trace_type resolved_in_trace" \ |
| { |
| global executable |
| global srcfile |
| global gdb_prompt |
| global lib_sl1 |
| |
| # Start with a fresh gdb. |
| clean_restart $executable |
| if ![runto_main] { |
| fail "Can't run to main" |
| 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\n(Thread .* hit )?Breakpoint.*marker.*at.*pending.c.*" \ |
| "continue to marker 1" |
| |
| set test "continue to marker 2" |
| gdb_test_multiple "continue" $test { |
| -re "Target returns error code .* too far .*$gdb_prompt $" { |
| if [string equal $trace_type "ftrace"] { |
| # Expected if the target was unable to install the |
| # fast tracepoint (e.g., jump pad too far from |
| # tracepoint). |
| pass "$test (too far)" |
| # Skip the rest of the tests. |
| return |
| } else { |
| fail $test |
| } |
| } |
| -re "Continuing.\r\n(Reading .* from remote target...\r\n)?\r\n(Thread .* hit )?Breakpoint.*marker.*at.*$srcfile.*$gdb_prompt $" { |
| pass $test |
| } |
| } |
| |
| 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" |
| }} |
| |
| # Verify pending tracepoint is resolved and installed during trace. |
| |
| proc pending_tracepoint_installed_during_trace { trace_type } \ |
| { with_test_prefix "$trace_type installed_in_trace" \ |
| { |
| global executable |
| global srcfile |
| global lib_sl1 |
| global gdb_prompt |
| global hex |
| |
| # Start with a fresh gdb. |
| clean_restart $executable |
| if ![runto_main] { |
| fail "Can't run to main" |
| 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\n(Thread .* hit )?Breakpoint.*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" |
| |
| set test "continue to marker 2" |
| gdb_test_multiple "continue" $test { |
| -re "Target returns error code .* too far .*$gdb_prompt $" { |
| if [string equal $trace_type "ftrace"] { |
| # Expected if the target was unable to install the |
| # fast tracepoint (e.g., jump pad too far from |
| # tracepoint). |
| pass "$test (too far)" |
| # Skip the rest of the tests. |
| return |
| } else { |
| fail $test |
| } |
| } |
| -re "Continuing.\r\n(Reading .* from remote target...\r\n)?\r\n(Thread .* hit )?Breakpoint.*marker.*at.*$srcfile.*$gdb_prompt $" { |
| pass $test |
| } |
| } |
| |
| 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" |
| |
| # powerpc64 shows "in .pendfunc2" here. |
| 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" |
| }} |
| |
| |
| # Verify pending tracepoint will no longer work if we disconnect during tracing. |
| |
| proc pending_tracepoint_disconnect_during_trace { trace_type } \ |
| { with_test_prefix "$trace_type disconn" \ |
| { |
| global executable |
| global srcfile |
| global lib_sl1 |
| global gdb_prompt |
| |
| # Start with a fresh gdb. |
| clean_restart $executable |
| if ![runto_main] { |
| fail "Can't run to main" |
| 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\n(Thread .* hit )?Breakpoint.*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" |
| } |
| } |
| } |
| } |
| }} |
| |
| |
| # Verify disconnect after pending tracepoint has been resolved. |
| |
| proc pending_tracepoint_disconnect_after_resolved { trace_type } \ |
| { with_test_prefix "$trace_type disconn_resolved" \ |
| { |
| global executable |
| global srcfile |
| global lib_sl1 |
| global gdb_prompt |
| |
| # Start with a fresh gdb. |
| clean_restart $executable |
| if ![runto_main] { |
| fail "Can't run to main" |
| 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\n(Thread .* hit )?Breakpoint.*marker.*at.*pending.c.*" \ |
| "continue to marker 1" |
| gdb_test "continue" "Continuing.\r\n(Reading .* from remote target...\r\n)?\r\n(Thread .* hit )?Breakpoint.*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" |
| } |
| } |
| }} |
| |
| # Verify action works properly in resolved tracepoint. |
| |
| proc pending_tracepoint_with_action_resolved { trace_type } \ |
| { with_test_prefix "$trace_type action_resolved" \ |
| { |
| global executable |
| global srcfile |
| global lib_sl1 |
| global gdb_prompt |
| global pcreg |
| |
| # Start with a fresh gdb. |
| clean_restart $executable |
| if ![runto_main] { |
| fail "Can't run to main" |
| 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_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\n(Thread .* hit )?Breakpoint.*marker.*at.*pending.c.*" \ |
| "continue to marker 1" |
| |
| set test "continue to marker 2" |
| gdb_test_multiple "continue" $test { |
| -re "Target returns error code .* too far .*$gdb_prompt $" { |
| if [string equal $trace_type "ftrace"] { |
| # Expected if the target was unable to install the |
| # fast tracepoint (e.g., jump pad too far from |
| # tracepoint). |
| pass "$test (too far)" |
| # Skip the rest of the tests. |
| return |
| } else { |
| fail $test |
| } |
| } |
| -re "Continuing.\r\n(Reading .* from remote target...\r\n)?\r\n(Thread .* hit )?Breakpoint.*marker.*at.*$srcfile.*$gdb_prompt $" { |
| pass "continue to marker 2" |
| } |
| |
| } |
| |
| 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" |
| }} |
| |
| 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 [get_in_proc_agent] |
| gdb_load_shlib $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" |