[PATCH v4 8/9] gdb/testsuite: support passing inferior arguments with native-gdbserver board

Michael Weghorn
2020-05-13T09:48:26Z

From: Simon Marchi <simon.marchi@efficios.com>

This patch makes it possible to run tests requiring passing arguments to
the inferior with the native-gdbserver board. The end goal is to write
a test that verifies passing arguments to the inferior works, and to
have that test exercise inferior arguments passed on the gdbserver
command line, when using the native-gdbserver target board (in addition
to the other boards). This is done in the next patch.

With the native-gdbserver target board, gdbserver is started in
gdb_reload (implemented in config/gdbserver.exp), called in gdb_run_cmd.
gdb_run_cmd already supposedly accepts inferior arguments (although that
feature does not seem to be used anywhere), which it passes to the `run`
command, for non-stub target boards. I've changed gdb_run_cmd so that
it forwards these arguments to gdb_reload as well. gdb_reload passes
them to gdbserver_run, and they eventually make their way to the
gdbserver command line.

gdb_run_cmd currently accepts `args` (the varargs of tcl), which means
it receives inferior arguments as a list. This won't work with
arguments with spaces, because they will end up being formatted with
curly braces like this:

% set args [list hello "with spaces" world]
hello {with spaces} world
% puts "run $args"
run hello {with spaces} world

I've changed it to accept a single string that is passed to `run` and
gdb_reload. I've done the same change in gdb_start_cmd and
gdb_starti_cmd, although these two are not used with native-gdbserver.

I've changed all gdb_reload implementations in the tree to accept a new
inferior_args argument, although most of them don't do anything with it
(and don't need to). People maintaining target boards out of tree will
need to do the same.

I found two tests to adjust to avoid adding new failures or errors.
These tests needed new [use_gdb_stub] checks, because they rely on
having GDB run new processes. These are guarded by a [target_info
exists noargs], which made them get skipped on native-gdbserver. But
now that the native-gdbserver board supports args, this is no longer
enough.

Note that with this change, noargs and use_gdb_stub are orthogonal. It
took me a moment to grasp this, so I thought I would spell out the
different possible situations:

- !noargs and !use_gdb_stub: inferior process started by gdb, can pass
args
- noargs and !use_gdb_stub: inferior process started by gdb (perhaps
through extended-remote protocol, the simulator, some other target),
but that target doesn't support inferior arguments
- noargs and use_gdb_stub: inferior process started by some other
program to which GDB connects using the remote protocol, that program
does not support passing args to the inferior process
- !noargs and use_gdb_stub: inferior process started by some other
program to which GDB connects u sing the remote protocol, that program
supports passing args to the inferior process

gdb/testsuite/ChangeLog:

* lib/gdb.exp (gdb_run_cmd): Change argument from args to
inferior_args. Pass it to gdb_reload.
(gdb_start_cmd, gdb_starti_cmd): Change argument from args to
inferior_args.
(gdb_reload): Add inferior_args argument.
* config/gdbserver.exp (gdb_reload): Add inferior_args argument,
pass it to gdbserver_run.
* boards/native-gdbserver.exp: Do not set noargs.
* boards/native-extended-gdbserver.exp (gdb_reload): Add
inferior_args argument.
* boards/stdio-gdbserver-base.exp (gdb_reload): Likewise.
* gdb.base/a2-run.exp: Check for use_gdb_stub.
* gdb.base/args.exp: Likewise.
---
.../boards/native-extended-gdbserver.exp | 2 +-
gdb/testsuite/boards/native-gdbserver.exp | 3 --
gdb/testsuite/boards/stdio-gdbserver-base.exp | 2 +-
gdb/testsuite/config/gdbserver.exp | 12 +++----
gdb/testsuite/gdb.base/a2-run.exp | 11 +++++-
gdb/testsuite/gdb.base/args.exp | 6 ++++
gdb/testsuite/lib/gdb.exp | 34 +++++++++++++------
7 files changed, 46 insertions(+), 24 deletions(-)

diff --git a/gdb/testsuite/boards/native-extended-gdbserver.exp b/gdb/testsuite/boards/native-extended-gdbserver.exp
index 465c1cc8ab..3d5e782114 100644
--- a/gdb/testsuite/boards/native-extended-gdbserver.exp
+++ b/gdb/testsuite/boards/native-extended-gdbserver.exp
@@ -102,7 +102,7 @@ proc gdb_file_cmd { arg } {
return [extended_gdbserver_load_last_file]
}

-proc gdb_reload { } {
+proc gdb_reload { {inferior_args {}} } {
return [extended_gdbserver_load_last_file]
}

diff --git a/gdb/testsuite/boards/native-gdbserver.exp b/gdb/testsuite/boards/native-gdbserver.exp
index f9a507261f..823f5cfa3a 100644
--- a/gdb/testsuite/boards/native-gdbserver.exp
+++ b/gdb/testsuite/boards/native-gdbserver.exp
@@ -27,9 +27,6 @@ load_board_description "local-board"
# This gdbserver can only run a process once per session.
set_board_info gdb,do_reload_on_run 1

-# There's no support for argument-passing (yet).
-set_board_info noargs 1
-
set_board_info use_gdb_stub 1
set_board_info exit_is_reliable 1

diff --git a/gdb/testsuite/boards/stdio-gdbserver-base.exp b/gdb/testsuite/boards/stdio-gdbserver-base.exp
index aafcf6991b..720e2e823f 100644
--- a/gdb/testsuite/boards/stdio-gdbserver-base.exp
+++ b/gdb/testsuite/boards/stdio-gdbserver-base.exp
@@ -45,7 +45,7 @@ proc make_gdbserver_stdio_port {} {
return "| [get_target_remote_pipe_cmd]"
}

-proc gdb_reload { } {
+proc gdb_reload { {inferior_args {}} } {
return [gdb_target_cmd "remote" [make_gdbserver_stdio_port]]
}

diff --git a/gdb/testsuite/config/gdbserver.exp b/gdb/testsuite/config/gdbserver.exp
index cb053b63e4..a4e935f214 100644
--- a/gdb/testsuite/config/gdbserver.exp
+++ b/gdb/testsuite/config/gdbserver.exp
@@ -36,12 +36,8 @@
# Unles you have a gdbserver that can handle multiple sessions.
#
# set_board_info noargs 1
-# At present there is no provision in the remote protocol
-# for passing arguments. This test framework does not
-# address the issue, so it's best to set this variable
-# in your baseboard configuration file.
-# FIXME: there's no reason why the test harness couldn't
-# pass commandline args when it spawns gdbserver.
+# Set this if the board does not support passing arguments to the
+# inferior process.
#
# set_board_info gdb,noinferiorio 1
# Neither the traditional gdbserver nor the one in libremote
@@ -77,8 +73,8 @@ proc gdbserver_gdb_load { } {
return [gdbserver_spawn ""]
}

-proc gdb_reload { } {
- return [gdbserver_run ""]
+proc gdb_reload { {inferior_args {}} } {
+ return [gdbserver_run $inferior_args]
}

proc gdb_reconnect { } {
diff --git a/gdb/testsuite/gdb.base/a2-run.exp b/gdb/testsuite/gdb.base/a2-run.exp
index 2e8ed60ec6..ea8f7ec95f 100644
--- a/gdb/testsuite/gdb.base/a2-run.exp
+++ b/gdb/testsuite/gdb.base/a2-run.exp
@@ -135,7 +135,7 @@ gdb_run_cmd 5
gdb_test_stdio "" "120" "" "run \"$testfile\" with arg"

# Run again with same arguments.
-gdb_run_cmd
+gdb_run_cmd 5

setup_xfail "arm-*-coff"
gdb_test_stdio "" "120" "" "run \"$testfile\" again with same args"
@@ -147,6 +147,15 @@ gdb_run_cmd

gdb_test_stdio "" "usage: factorial <number>" "" "run after setting args to nil"

+# The remaining tests pass inferior arguments through GDB, so doesn't
+# work with stub targets, where GDB connects to debug an already started
+# process.
+
+if [use_gdb_stub] {
+ verbose "Skipping rest of a2-run.exp because target is a stub."
+ return
+}
+
# Use "set args" command to specify an argument and run again.
gdb_test_no_output "set args 6"

diff --git a/gdb/testsuite/gdb.base/args.exp b/gdb/testsuite/gdb.base/args.exp
index 6c416fcfc8..ee75445c0b 100644
--- a/gdb/testsuite/gdb.base/args.exp
+++ b/gdb/testsuite/gdb.base/args.exp
@@ -23,6 +23,12 @@ if [target_info exists noargs] {
return
}

+# This test requires starting new inferior processes, skip it if the target
+# board is a stub.
+if [use_gdb_stub] {
+ return
+}
+
standard_testfile

if {[build_executable $testfile.exp $testfile \
diff --git a/gdb/testsuite/lib/gdb.exp b/gdb/testsuite/lib/gdb.exp
index 3c6f0d76d6..ec77cfb0d3 100644
--- a/gdb/testsuite/lib/gdb.exp
+++ b/gdb/testsuite/lib/gdb.exp
@@ -245,10 +245,13 @@ proc target_can_use_run_cmd {} {
# Using ``.*$'' could swallow up output that we attempt to match
# elsewhere.
#
+# INFERIOR_ARGS is passed as arguments to the start command, so may contain
+# inferior arguments.
+#
# N.B. This function does not wait for gdb to return to the prompt,
# that is the caller's responsibility.

-proc gdb_run_cmd {args} {
+proc gdb_run_cmd { {inferior_args {}} } {
global gdb_prompt use_gdb_stub

foreach command [gdb_init_commands] {
@@ -264,7 +267,7 @@ proc gdb_run_cmd {args} {

if $use_gdb_stub {
if [target_info exists gdb,do_reload_on_run] {
- if { [gdb_reload] != 0 } {
+ if { [gdb_reload $inferior_args] != 0 } {
return
}
send_gdb "continue\n"
@@ -309,7 +312,7 @@ proc gdb_run_cmd {args} {
send_gdb "y\n" answer
}
-re "The program is not being run.*$gdb_prompt $" {
- if { [gdb_reload] != 0 } {
+ if { [gdb_reload $inferior_args] != 0 } {
return
}
send_gdb "jump *$start\n"
@@ -324,11 +327,11 @@ proc gdb_run_cmd {args} {
}

if [target_info exists gdb,do_reload_on_run] {
- if { [gdb_reload] != 0 } {
+ if { [gdb_reload $inferior_args] != 0 } {
return
}
}
- send_gdb "run $args\n"
+ send_gdb "run $inferior_args\n"
# This doesn't work quite right yet.
# Use -notransfer here so that test cases (like chng-sym.exp)
# may test for additional start-up messages.
@@ -347,10 +350,13 @@ proc gdb_run_cmd {args} {
# Generic start command. Return 0 if we could start the program, -1
# if we could not.
#
+# INFERIOR_ARGS is passed as arguments to the start command, so may contain
+# inferior arguments.
+#
# N.B. This function does not wait for gdb to return to the prompt,
# that is the caller's responsibility.

-proc gdb_start_cmd {args} {
+proc gdb_start_cmd { {inferior_args {}} } {
global gdb_prompt use_gdb_stub

foreach command [gdb_init_commands] {
@@ -368,7 +374,7 @@ proc gdb_start_cmd {args} {
return -1
}

- send_gdb "start $args\n"
+ send_gdb "start $inferior_args\n"
# Use -notransfer here so that test cases (like chng-sym.exp)
# may test for additional start-up messages.
gdb_expect 60 {
@@ -386,10 +392,13 @@ proc gdb_start_cmd {args} {
# Generic starti command. Return 0 if we could start the program, -1
# if we could not.
#
+# INFERIOR_ARGS is passed as arguments to the starti command, so may contain
+# inferior arguments.
+#
# N.B. This function does not wait for gdb to return to the prompt,
# that is the caller's responsibility.

-proc gdb_starti_cmd {args} {
+proc gdb_starti_cmd { {inferior_args {}} } {
global gdb_prompt use_gdb_stub

foreach command [gdb_init_commands] {
@@ -407,7 +416,7 @@ proc gdb_starti_cmd {args} {
return -1
}

- send_gdb "starti $args\n"
+ send_gdb "starti $inferior_args\n"
gdb_expect 60 {
-re "The program .* has been started already.*y or n. $" {
send_gdb "y\n" answer
@@ -4817,8 +4826,13 @@ proc gdb_load { arg } {
# either the first time or after already starting the program once,
# for remote targets. Most files that override gdb_load should now
# override this instead.
+#
+# INFERIOR_ARGS contains the arguments to pass to the inferiors, as a
+# single string to get interpreted by a shell. If the target board
+# overriding gdb_reload is a "stub", then it should arrange things such
+# these arguments make their way to the inferior process.

-proc gdb_reload { } {
+proc gdb_reload { {inferior_args {}} } {
# For the benefit of existing configurations, default to gdb_load.
# Specifying no file defaults to the executable currently being
# debugged.
--
2.26.2