aboutsummaryrefslogtreecommitdiff
path: root/gdb/testsuite/gdb.base/inferior-args.exp
blob: 9406c7882f043bdb8982dc3ca387bb4c1bf1092b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
# 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
	    }
	}
    }
}