|  | #   Copyright (C) 2012-2024 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/>. | 
|  |  | 
|  | standard_testfile | 
|  |  | 
|  | set flags {} | 
|  | lappend flags debug | 
|  | lappend_include_file flags $srcdir/lib/unbuffer_output.c | 
|  |  | 
|  | if { [prepare_for_testing "failed to prepare" $testfile $srcfile $flags] } { | 
|  | return -1 | 
|  | } | 
|  |  | 
|  | set bp_location1 [gdb_get_line_number "set breakpoint 1 here"] | 
|  | set dp_location1 [gdb_get_line_number "set dprintf 1 here"] | 
|  |  | 
|  | if ![runto_main] { | 
|  | return -1 | 
|  | } | 
|  |  | 
|  | gdb_test "dprintf" "Format string required" | 
|  |  | 
|  | gdb_test "dprintf foo" "Format string required" | 
|  |  | 
|  | gdb_test "dprintf 29" "Format string required" | 
|  |  | 
|  | delete_breakpoints | 
|  |  | 
|  | gdb_breakpoint "main" | 
|  |  | 
|  | gdb_test "dprintf foo,\"At foo entry\\n\"" \ | 
|  | "Dprintf .*" | 
|  |  | 
|  | gdb_test "ignore \$bpnum 1" ".*Will ignore next crossing of breakpoint.*" | 
|  |  | 
|  | gdb_test "dprintf $dp_location1,\"arg=%d, g=%d\\n\", arg, g" \ | 
|  | "Dprintf .*" | 
|  |  | 
|  | gdb_test_sequence "info breakpoints" "dprintf info 1" { | 
|  | "\[\r\n\]Num     Type           Disp Enb Address +What" | 
|  | "\[\r\n\]2       breakpoint" | 
|  | "\[\r\n\]3       dprintf" | 
|  | "\[\r\n\]        printf \"At foo entry\\\\n\"" | 
|  | "\[\r\n\]4       dprintf" | 
|  | "\[\r\n\]        printf \"arg=%d, g=%d\\\\n\", arg, g" | 
|  | } | 
|  |  | 
|  | gdb_test "break $bp_location1" \ | 
|  | "Breakpoint .*" | 
|  |  | 
|  | gdb_run_cmd | 
|  |  | 
|  | gdb_test "" "Breakpoint" | 
|  |  | 
|  | gdb_test "continue" "arg=1234, g=1234.*" "1st dprintf, gdb" | 
|  |  | 
|  | gdb_test "continue" "At foo entry.*arg=1235, g=2222.*" "2nd dprintf, gdb" | 
|  |  | 
|  | # Restart GDB and set set up for testing. | 
|  |  | 
|  | proc restart {} { | 
|  | global binfile | 
|  | global bp_location1 dp_location1 | 
|  |  | 
|  | clean_restart $binfile | 
|  |  | 
|  | if ![runto_main] { | 
|  | return -1 | 
|  | } | 
|  |  | 
|  | gdb_test "dprintf foo,\"At foo entry\\n\"" \ | 
|  | "Dprintf .*" | 
|  |  | 
|  | gdb_test "dprintf $dp_location1,\"arg=%d, g=%d\\n\", arg, g" \ | 
|  | "Dprintf .*" | 
|  |  | 
|  | gdb_test "break $bp_location1" "Breakpoint .*" | 
|  | } | 
|  |  | 
|  | # Test continuing across a dprintf.  PATTERN matches the output | 
|  | # generated by the dprintf.  MSG is used as test message. | 
|  |  | 
|  | proc test_dprintf {pattern msg} { | 
|  | gdb_test_stdio "continue" $pattern "" "$msg" | 
|  | } | 
|  |  | 
|  | # Test the "call" style. | 
|  |  | 
|  | proc test_call {} { | 
|  | global binfile | 
|  | global bp_location1 | 
|  |  | 
|  | # Now switch styles and rerun; in the absence of redirection the | 
|  | # output should be the same. | 
|  |  | 
|  | with_test_prefix "printf" { | 
|  | restart | 
|  |  | 
|  | gdb_test_no_output "set dprintf-style call" "set dprintf style to call" | 
|  |  | 
|  | test_dprintf "At foo entry.*arg=1234, g=1234\r\n" "1st dprintf" | 
|  |  | 
|  | test_dprintf "At foo entry.*arg=1235, g=2222\r\n" "2nd dprintf" | 
|  | } | 
|  |  | 
|  | gdb_test_multiple "print stderr" "stderr symbol check" { | 
|  | -re "\\'stderr\\' has unknown type.*" { | 
|  | untested "No information available for stderr, exiting early" | 
|  | return | 
|  | } | 
|  | -re "\\\$1.*" { | 
|  | pass $gdb_test_name | 
|  | } | 
|  | } | 
|  |  | 
|  | with_test_prefix "fprintf" { | 
|  | restart | 
|  |  | 
|  | gdb_test_no_output "set dprintf-function fprintf" "set dprintf function" | 
|  | gdb_test_no_output "set dprintf-channel stderr" "set dprintf channel" | 
|  |  | 
|  | gdb_test_no_output "set dprintf-style call" "set dprintf style to call" | 
|  |  | 
|  | test_dprintf "At foo entry.*arg=1234, g=1234\r\n" "1st dprintf" | 
|  |  | 
|  | test_dprintf "At foo entry.*arg=1235, g=2222\r\n" "2nd dprintf" | 
|  | } | 
|  | } | 
|  |  | 
|  | # The "call" style depends on having I/O functions available. | 
|  |  | 
|  | if ![target_info exists gdb,noinferiorio] { | 
|  | with_test_prefix "call" { | 
|  | test_call | 
|  | } | 
|  | } | 
|  |  | 
|  | # Test the "agent" style. | 
|  |  | 
|  | proc test_agent {} { | 
|  | global binfile | 
|  | global gdb_prompt | 
|  |  | 
|  | restart | 
|  |  | 
|  | set target_can_dprintf 1 | 
|  | set msg "set dprintf style to agent" | 
|  | gdb_test_multiple "set dprintf-style agent" $msg { | 
|  | -re "warning: Target cannot run dprintf commands.*\r\n$gdb_prompt $" { | 
|  |  | 
|  | # The target reports that it doesn't support target side | 
|  | # commands at all. | 
|  | set target_can_dprintf 0 | 
|  | unsupported "$msg" | 
|  | } | 
|  | -re ".*$gdb_prompt $" { | 
|  | pass "$msg" | 
|  | } | 
|  | } | 
|  |  | 
|  | if !$target_can_dprintf { | 
|  | return | 
|  | } | 
|  |  | 
|  | # Even if the target reports that it does support target side | 
|  | # commands, we can only tell that it supports them in combination | 
|  | # with a particular breakpoint type (Z0, Z1, etc.) when we try to | 
|  | # insert the breakpoint.  When "set breakpoint always-inserted is | 
|  | # off", that'll be on next continue. | 
|  | set msg "1st dprintf" | 
|  | gdb_test_multiple "continue" $msg { | 
|  | -re "Warning:.*Target doesn't support breakpoints that have target side commands.*\r\n$gdb_prompt $" { | 
|  | set target_can_dprintf 0 | 
|  | unsupported "$msg" | 
|  | } | 
|  | -re "Breakpoint \[0-9\]+, foo .*$gdb_prompt $" { | 
|  | pass "$msg" | 
|  | } | 
|  | } | 
|  |  | 
|  | if $target_can_dprintf { | 
|  | gdb_test "continue" "Breakpoint \[0-9\]+, foo .*" "2nd dprintf" | 
|  |  | 
|  | gdb_test_sequence "info breakpoints" "dprintf info" { | 
|  | "\[\r\n\]Num     Type           Disp Enb Address +What" | 
|  | "\[\r\n\]1       breakpoint" | 
|  | "\[\r\n\]\tbreakpoint already hit 1 time" | 
|  | "\[\r\n\]2       dprintf" | 
|  | "\[\r\n\]        agent-printf \"At foo entry\\\\n\"" | 
|  | "\[\r\n\]3       dprintf" | 
|  | "\[\r\n\]        agent-printf \"arg=%d, g=%d\\\\n\", arg, g" | 
|  | "\[\r\n\]4       breakpoint" | 
|  | "\[\r\n\]\tbreakpoint already hit 2 times" | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | with_test_prefix "agent" { | 
|  | test_agent | 
|  | } | 
|  |  | 
|  | gdb_test "set dprintf-style foobar" "Undefined item: \"foobar\"." \ | 
|  | "Set dprintf style to an unrecognized type" | 
|  |  | 
|  | # Test that force-disabling the BreakpointCommands RSP feature works | 
|  | # as expected.  dprintf relies on support for target-side breakpoint | 
|  | # commands --- use it as proxy. | 
|  | if [gdb_protocol_is_remote] { | 
|  | gdb_test \ | 
|  | "set remote breakpoint-commands-packet off" \ | 
|  | "Support for the 'BreakpointCommands' packet on the current remote target is set to \"off\"." | 
|  |  | 
|  | gdb_test "set dprintf-style agent" \ | 
|  | "warning: Target cannot run dprintf commands.*" \ | 
|  | "set dprintf-style agent, with feature disabled" | 
|  | } |