gdb/gdbserver: add a '--no-escape-args' command line option

This introduces a new '--no-escape-args' option for gdb and gdbserver.

I (Andrew Burgess) have based this patch from work done in this
series:

  https://inbox.sourceware.org/gdb-patches/20211022071933.3478427-1-m.weghorn@posteo.de/

I have changed things slightly from the original series.  I think this
work is close enough that I've left the original author (Michael) in
place and added myself as co-author.  Any bugs introduced by my
modifications to the original patch should be considered mine.  I've
also added documentation and tests which were missing from the
originally proposed patch.

When the startup-with-shell option is enabled, arguments passed
directly as 'gdb --args <args>' or 'gdbserver <args>', are by default
escaped so that they are passed to the inferior as passed on the
command line, no globbing or variable substitution happens within the
shell GDB uses to start the inferior.

For gdbserver, this is the case since commit:

  commit bea571ebd7
  Date:   Mon May 25 11:39:43 2020 -0400

      Use construct_inferior_arguments which handles special chars

Only arguments set via 'set args <args>', 'run <args>', or through the
Python API are not escaped in standard upstream GDB right now.

For the 'gdb --args' case, directly setting unescaped args on gdb
invocation is possible e.g. by using the "--eval-command='set args
<args>'", while this possibility does not exist for gdbserver.

This commit adds a new '--no-escape-args' command line option for GDB
and gdbserver.  This option is used with GDB as a replacement for the
current '--args' option, and for gdbserver this new option is a flag
which changes how gdbserver handles inferior arguments on the command
line.  When '--no-escape-args' is used inferior arguments passed on
the command line will not have escaping added by GDB or gdbserver.

For gdbserver, using this new option allows having the behaviour from
before commit bea571ebd7, while keeping
the default behaviour unified between GDB and GDBserver.

For GDB the --no-escape-args option can be used as a replacement for
--args, like this:

  shell> gdb --no-escape-args my-program arg1 arg2 arg3

While for gdbserver, the --no-escape-args option is a flag, which can
be used like:

  shell> gdbserver --no-escape-args --once localhost:54321 \
             my-program arg1 arg2 arg3

Co-Authored-By: Andrew Burgess <aburgess@redhat.com>
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=28392

Reviewed-By: Eli Zaretskii <eliz@gnu.org>
Tested-By: Guinevere Larsen <guinevere@redhat.com>
This commit is contained in:
Michael Weghorn
2021-10-22 07:19:29 +00:00
committed by Andrew Burgess
parent 13793e3983
commit e5e76451fa
7 changed files with 434 additions and 48 deletions

View File

@@ -3851,10 +3851,20 @@ gdbserver_usage (FILE *stream)
" --startup-with-shell\n"
" Start PROG using a shell. I.e., execs a shell that\n"
" then execs PROG. (default)\n"
" To make use of globbing and variable subsitution for\n"
" arguments passed directly on gdbserver invocation,\n"
" see the --no-escape-args command line option in\n"
" addition\n"
" --no-startup-with-shell\n"
" Exec PROG directly instead of using a shell.\n"
" Disables argument globbing and variable substitution\n"
" on UNIX-like systems.\n"
" --no-escape-args\n"
" If PROG is started using a shell (see the\n"
" --[no-]startup-with-shell option),\n"
" ARGS passed directly on gdbserver invocation are\n"
" escaped, so no globbing or variable substitution\n"
" happens for those. This option disables escaping, so\n"
" globbing and variable substituation in the shell\n"
" are done for ARGS on UNIX-like systems.\n"
"\n"
"Debug options:\n"
"\n"
@@ -4110,6 +4120,7 @@ captured_main (int argc, char *argv[])
volatile bool multi_mode = false;
volatile bool attach = false;
bool selftest = false;
bool escape_args = true;
#if GDB_SELF_TEST
std::vector<const char *> selftest_filters;
@@ -4132,7 +4143,7 @@ captured_main (int argc, char *argv[])
OPT_DEBUG, OPT_DEBUG_FILE, OPT_DEBUG_FORMAT, OPT_DISABLE_PACKET,
OPT_DISABLE_RANDOMIZATION, OPT_NO_DISABLE_RANDOMIZATION,
OPT_STARTUP_WITH_SHELL, OPT_NO_STARTUP_WITH_SHELL, OPT_ONCE,
OPT_SELFTEST,
OPT_SELFTEST, OPT_NO_ESCAPE
};
static struct option longopts[] =
@@ -4157,6 +4168,7 @@ captured_main (int argc, char *argv[])
OPT_NO_STARTUP_WITH_SHELL},
{"once", no_argument, nullptr, OPT_ONCE},
{"selftest", optional_argument, nullptr, OPT_SELFTEST},
{"no-escape-args", no_argument, nullptr, OPT_NO_ESCAPE},
{nullptr, no_argument, nullptr, 0}
};
@@ -4360,6 +4372,10 @@ captured_main (int argc, char *argv[])
}
break;
case OPT_NO_ESCAPE:
escape_args = false;
break;
case '?':
/* Figuring out which element of ARGV contained the invalid
argument is not simple. There are a couple of cases we need
@@ -4475,7 +4491,8 @@ captured_main (int argc, char *argv[])
int n = argc - (next_arg - argv);
program_args
= construct_inferior_arguments ({&next_arg[1], &next_arg[n]}, true);
= construct_inferior_arguments ({&next_arg[1], &next_arg[n]},
escape_args);
/* Wait till we are at first instruction in program. */
target_create_inferior (program_path.get (), program_args);