| # Copyright 2020-2025 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/>. |
| |
| # Test running an inferior with arguments. |
| |
| # This does not work on boards that don't support inferior arguments. |
| require {!target_info exists noargs} |
| |
| standard_testfile .c |
| |
| if {[build_executable "failed to prepare" $testfile $srcfile \ |
| {debug additional_flags=-std=c99}] == -1} { |
| return |
| } |
| |
| # STARTUP_WITH_SHELL is either 'on' or 'off' and determines if the |
| # inferior is started under a shell or not. INFERIOR_ARGS is the list |
| # of inferior arguments. EXPECTED_RESULTS is the list of expected |
| # results, one for each argument. |
| # |
| # When STUB_SUITABLE is true this test is suitable for use with |
| # gdbserver, i.e. INFERIOR_ARGS can be passed through to |
| # gdbserver_start via gdb_run_cmd. Some of the weird quoting used in |
| # some of the tests doesn't seem to play well with gdbserver_start. |
| # This is a TCL issue, not a gdbserver issue. Manually testing with |
| # gdbserver shows no problems. It's just that when we try to invoke |
| # gdbserver from TCL the argument quoting gets messed up. For tests |
| # that are problematic, STUB_SUITABLE is false. |
| proc do_test { method startup_with_shell inferior_args expected_results \ |
| stub_suitable } { |
| global binfile hex |
| |
| clean_restart $binfile |
| |
| gdb_test_no_output "set startup-with-shell $startup_with_shell" |
| |
| if { $method == "start" } { |
| # The start command does not make sense for a stub. |
| if { [use_gdb_stub] } { |
| return; |
| } |
| |
| if { [gdb_start_cmd $inferior_args] < 0 } { |
| fail "could not issue start command" |
| return -1 |
| } |
| |
| # Consume up to the GDB prompt after the stop. |
| gdb_test "" ".*main.*" "stop at main" |
| |
| } elseif { $method == "starti" } { |
| # The starti command does not make sense for a stub. |
| if { [use_gdb_stub] } { |
| return; |
| } |
| |
| if { [gdb_starti_cmd $inferior_args] < 0 } { |
| fail "could not issue start command" |
| return -1 |
| } |
| |
| # Consume up to the GDB prompt after the stop. |
| gdb_test "" "" "stop at first instruction" |
| |
| # Put a breakpoint and continue until main. |
| if { ![gdb_breakpoint "main" message] } { |
| fail "could not set breakpoint on main" |
| return -1 |
| } |
| |
| if { [gdb_continue "main"] != 0 } { |
| fail "could not continue to main" |
| return -1 |
| } |
| |
| } elseif { $method == "run" } { |
| if { ![gdb_breakpoint "main" message] } { |
| fail "could not set breakpoint on main" |
| return -1 |
| } |
| |
| if { [use_gdb_stub] && !$stub_suitable } { |
| return |
| } |
| |
| # The run command does not make sense for a stub, but GDB_RUN_CMD |
| # does the right thing when the target is a stub (start the stub, |
| # connect to it, and "continue"). |
| # |
| # This allows us to test arguments passed on the gdbserver command |
| # line. |
| if { [gdb_run_cmd $inferior_args] < 0 } { |
| fail "could not run" |
| return -1 |
| } |
| |
| # Consume up to the GDB prompt after the stop. |
| gdb_test "" ".*main.*" "stop at main" |
| |
| } elseif { $method == "set args" } { |
| # Using "set args" does not make sense with a stub. |
| if { [use_gdb_stub] } { |
| return; |
| } |
| |
| gdb_test_no_output "set args $inferior_args" |
| |
| if { ![runto_main] } { |
| return -1 |
| } |
| |
| } else { |
| error "invalid method $method" |
| } |
| |
| set argc [expr [llength $expected_results] + 1] |
| |
| # Now that we are stopped at main, inspect argc/argv. |
| gdb_test "print argc" " = $argc" |
| gdb_test "print argv\[0\]" " = $hex \"\[^\r\n\]+\"" |
| for { set i 1 } { $i < $argc } { incr i } { |
| set idx [expr $i - 1] |
| gdb_test "print argv\[$i\]" " = [lindex $expected_results $idx]" |
| } |
| } |
| |
| set test_desc_list [] |
| |
| # test one |
| # -------- |
| # |
| # The second arg is an empty string on purpose. The last argument |
| # must be the empty argument -- we once had a bug where that wouldn't |
| # work! |
| lappend test_desc_list [list "test one" \ |
| true \ |
| { "first arg" "" "third-arg" "'" "\"" " " "" } \ |
| [list "$hex \"first arg\"" \ |
| "$hex \"\"" \ |
| "$hex \"third-arg\"" \ |
| "$hex \"'\"" \ |
| "$hex \"\\\\\"\"" \ |
| "$hex \" \"" \ |
| "$hex \"\"" ]] |
| |
| # test two |
| # -------- |
| # |
| # The argument being passed here is '"', that is a single double quote |
| # contained within single quotes. |
| # |
| # I build the test descriptor using this mess of code to avoid having |
| # unbalanced quotes, which messes up indentation and syntax |
| # highlighting within (at least) emacs. The 'format' of ascii code 34 |
| # gives us the double quote character. Then I have to jump through |
| # the rest of this mess in order to avoid TCL escaping the quote for |
| # me. It's super important that what we send to GDB is '"' not '\"'. |
| set item [list "test two" false] |
| set cmd [format "lappend item \{ '%c' '\\%c' \}" 34 34] |
| eval $cmd |
| set bs "\\\\" |
| lappend item [list "$hex \"$bs\"\"" "$hex \"$bs$bs$bs\"\""] |
| lappend test_desc_list $item |
| |
| # test three |
| # ---------- |
| # |
| # This test focuses on sending special shell characters within a |
| # double quote argument, and each special character is prefixed with a |
| # backslash. |
| # |
| # In a POSIX shell, within a double quoted argument, only $ (dollar), |
| # ` (backtick), " (double quote), \ (backslash), and newline can be |
| # escaped. All other backslash characters are literal backslashes. |
| # |
| # As with the previous test, the double quotes are lost when the |
| # arguments are sent through gdbserver_start, as such, this test isn't |
| # going to work when using the native-gdbserver board, hence we set |
| # the second arguemnt to 'false'. |
| lappend test_desc_list [list "test three" \ |
| false \ |
| { "\&" "\<" "\#" "\^" "\>" "\$" "\`" } \ |
| [list "$hex \"\\\\\\\\&\"" \ |
| "$hex \"\\\\\\\\<\"" \ |
| "$hex \"\\\\\\\\#\"" \ |
| "$hex \"\\\\\\\\\\^\"" \ |
| "$hex \"\\\\\\\\>\"" \ |
| "$hex \"\\\$\"" \ |
| "$hex \"`\""]] |
| |
| # test four |
| # --------- |
| # |
| # This test passes two arguments, a single and double quote, each |
| # escaped with a backslash. |
| lappend test_desc_list [list "test four" \ |
| true \ |
| { \' \" } \ |
| [list "$hex \"'\"" \ |
| "$hex \"\\\\\"\""]] |
| |
| foreach desc $test_desc_list { |
| lassign $desc name stub_suitable args re_list |
| with_test_prefix $name { |
| foreach_with_prefix set_method { "start" "starti" "run" "set args" } { |
| foreach_with_prefix startup_with_shell { on off } { |
| do_test $set_method $startup_with_shell $args $re_list \ |
| $stub_suitable |
| } |
| } |
| } |
| } |