From: Andrew Burgess Date: Fri, 1 Aug 2025 11:22:38 +0000 (+0100) Subject: gdbserver: allow gnu style arguments to gdbserver X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=ce1b10c1ab3fc6f32621f1f23cc116ee8e39d473;p=thirdparty%2Fbinutils-gdb.git gdbserver: allow gnu style arguments to gdbserver Now that we use getopt_long for argument processing in gdbserver, it is relatively easy to support GNU style arguments, that is, arguments passed without an '=' between the argument and the value. As support for GNU style arguments is the default from getopt_long, the first part of this commit is to remove the code which deliberately disables the GNU argument support. With that done, we now need to consider optional arguments. In this case, getopt_long doesn't automatically grab the next word from ARGV to be the argument value, so I've added some code to do this. I've also tried to make this code a little smart. As the first argument passed to gdbserver that doesn't have a '--' at the start is the PORT number, the new code block I've added tries to spot if the argument value might be the port number. If it is, then we don't allow the port number to become the argument value, and instead, we pretend the argument value is missing. This seems to give better error messages. There are going to be UI changes in how gdbserver handles incorrect arguments after this commit. However, the behaviour for valid command lines should be unchanged. Approved-By: Tom Tromey --- diff --git a/gdbserver/server.cc b/gdbserver/server.cc index 5ad60be5b47..1e0be1cc69b 100644 --- a/gdbserver/server.cc +++ b/gdbserver/server.cc @@ -4204,25 +4204,58 @@ captured_main (int argc, char *argv[]) while ((longindex = -1, optc = getopt_long (argc, argv, "+", longopts, &longindex)) != -1) { - /* We only support '--option=value' form, not '--option value'. To - achieve this, if global OPTARG points to the start of the previous - ARGV entry, then we must have used the second (unsupported) form, - so set OPTARG to NULL and decrement OPTIND to make it appear that - there was no value passed. If the option requires an argument, - then this means we should convert OPTC to '?' to indicate an - error. */ + /* As a GNU extension, getopt_long supports '--arg value' form, + without an '=' symbol between the 'arg' and the 'value'. This + block aids in supporting this form. + + If we found a matching entry in LONGOPTS, the entry has an + optional argument, and OPTARG is NULL, then this indicates that we + saw the '--arg value' form. Look at the next ARGV entry to see if + it exists, and doesn't look like a port number, or the start of + another argument. If this is the case, then make the next ARGV + entry the argument value. Otherwise, continue with no + argument. + + If we found a matching entry in LONGOPTS, the entry has a required + argument, then OPTARG will not be NULL. In this case, if the + start of OPTARG is the start of the previous ARGV entry, then this + indicates we saw the '--arg value' form. If OPTARG looks like a + port number, or the start of another argument, then assume the + user didn't in fact pass a value, but forgot. Pretend we are + missing the argument value. */ if (longindex != -1 - && longopts[longindex].has_arg != no_argument) + && ((longopts[longindex].has_arg == optional_argument + &&optarg == nullptr) + || (longopts[longindex].has_arg == required_argument + && optarg == argv[optind - 1]))) { - if (optarg == argv[optind - 1]) + if (longopts[longindex].has_arg == optional_argument) { - optarg = nullptr; - --optind; + /* Claim the next entry from ARGV as the argument value. */ + optarg = argv[optind]; + optind++; } + else + gdb_assert (optarg != nullptr); - if (longopts[longindex].has_arg == required_argument - && optarg == nullptr) - optc = '?'; + if (optarg == nullptr + || strcmp (optarg, "-") == 0 + || strcmp (optarg, STDIO_CONNECTION_NAME) == 0 + || startswith (optarg, "--") + || strchr (optarg, ':') != nullptr) + { + /* OPTARG is NULL, looks like a port number, or could be the + start of another argument. Clear OPTARG as we don't have + an argument, and decrement OPTIND so the next call to + getopt will process this as an argument. */ + optarg = nullptr; + optind--; + + /* For required arguments, if we don't have an argument, then + this is an errror, set OPTC to reflect this. */ + if (longopts[longindex].has_arg == required_argument) + optc = '?'; + } } switch (optc)