From: Kevin Buettner <kevinb@redhat.com>
To: Andrew Burgess <aburgess@redhat.com>
Cc: gdb-patches@sourceware.org, Michael Weghorn <m.weghorn@posteo.de>,
Eli Zaretskii <eliz@gnu.org>,
Guinevere Larsen <guinevere@redhat.com>
Subject: Re: [PATCH] gdb/gdbserver: pass inferior arguments as a single string
Date: Tue, 24 Jun 2025 14:50:52 -0700 [thread overview]
Message-ID: <20250624145052.4659642b@f41-zbm-amd> (raw)
In-Reply-To: <a18a112d8d0957bc327311184cc14dbbc5ac1f0b.1747132216.git.aburgess@redhat.com>
Hi Andrew,
I have a few commit log nits - see (inline) below.
On Tue, 13 May 2025 11:31:04 +0100
Andrew Burgess <aburgess@redhat.com> wrote:
> GDB holds the inferior arguments as a single string. Currently when
> GDB needs to pass the inferior arguments to a remote target as part of
> a vRun packet, this is done by splitting the single argument string
> into its component arguments by calling gdb::remote_args::split, which
> uses the gdb_argv class to split the arguments for us.
>
> The same gdb_argv class is used when the user has asked GDB/gdbserver
> to start the inferior without first invoking a shell; the gdb_argv
> class is used to split the argument string into it component
> arguments, and each is passed as a separate argument to the execve
> call which spawns the inferior.
>
> There is however, a problem with using gdb_argv to split the arguments
> before passing them to a remote target. To understand this problem we
> must first understand how gdb_argv is used when invoking an inferior
> without a shell.
>
> And to understand how gdb_argv is used to start an inferior without a
> shell, I feel we need to first look at an example of starting an
> inferior with a shell.
>
> Consider these two cases:
>
> (a) (gdb) set args \$VAR
> (b) (gdb) set args $VAR
>
> When starting with a shell, in case (a) the user expects the inferior
> to receive a literal '$VAR' string as an argument, while in case (b)
> the user expects to see the shell expanded value of the variable $VAR.
>
> If the user does 'set startup-with-shell off', then in (a) GDB will
> strip the '\' while splitting the arguments, and the inferior will be
> passed a literal '$VAR'. In (b) there is no '\' to strip, so also in
> this case the inferior will receive a literal '$VAR', remember
> startup-with-shell is off, so there is no shell than can ever expand
s/than/that/
> $VAR.
>
> Notice, that when startup-with-shell is off, we end up with a many to
> one mapping, both (a) and (b) result in the literal string $VAR being
> passed to the inferior. I think this is the correct behaviour in this
> case.
>
> However, as we use gdb_argv to split the remote arguments we have the
> same many to one mapping within the vRun packet. But the vRun packet
> will be used when startup-with-shell is both on and off. What this
> means is that when gdbserver receives a vRun packet containing '$VAR'
> it doesn't know if GDB actually had '$VAR', or if GDB had '\$VAR'.
> And this is a huge problem.
>
> We can address this by making the argument splitting for remote
> targets smarter, and I do have patches that try to do this in this
> series:
>
> https://inbox.sourceware.org/gdb-patches/cover.1730731085.git.aburgess@redhat.com
>
> That series was pretty long, and wasn't getting reviewed, so I'm
> pulling the individual patches out and posting them separately.
>
> This patch doesn't try to make remote argument splitting. I think
s/make/do/
> that splitting and then joining the arguments is a mistake which can
> only introduce problems. The patch in the above series which tries to
> make the splitting and joining "smarter" handles unquoted, single
> quoted, and double quoted strings. But doesn't really address
s/But doesn't/But that doesn't/
> parameter substitution, command substitution, or arithmetic expansion.
> And even if we did try to address these cases, what rules exactly
> would we implement? Probably POSIX shell rules, but what if the
> remote target doesn't have a POSIX shell? The only reason we're
> talking about which shell rules to follow is because the splitting and
> joining logic needs to mirror those rules. If we stop splitting and
> joining then we no longer need to care about the target's shell.
>
> Clearly, for backward compatibility we need to maintain some degree of
> argument splitting and joining as we currently have; and that's why I
> have a later patch (see the series above) that tries to improve that
> splitting and joining a little. But I think, what we should really
> do, is add a new feature flag (as used by the qSupported packet) and,
> if GDB and the remote target agree, we should pass the inferior
> arguments as a single string.
>
> This solves all our problems. In the startup with shell case, we no
> longer need to worry about splitting at all. The arguments are passed
> unmodified to the remote target, that can then pass the arguments to
> the shell directly.
>
> In the 'startup-with-shell off' case it is now up to the remote target
> to split the arguments, though in gdbserver we already did this, so
> nothing really changes in this case. And if the remote target doesn't
> have a POSIX shell, well GDB just doesn't need to worry about it!
>
> Something similar to this was originally suggested in this series:
>
> https://inbox.sourceware.org/gdb-patches/20211022071933.3478427-1-m.weghorn@posteo.de/
>
> though this series didn't try to maintain backward compatibility,
> which I think is an issue that my patch solves. Additionally, this
> series only passed the arguments as a single string in some cases,
> I've simplified this so that, when GDB and the remote agree, the
> arguments are always passed as a single string. I think this is a
> little cleaner.
>
> I've also added documentation and some tests with this commit,
> including ensuring that we test both the new single string approach,
> and the fallback split/join approach.
>
> I've credited the author of the referenced series as co-author as they
> did come to a similar conclusion, though I think my implementation is
> different enough that I'm happy to list myself as primary author.
>
> Co-Authored-By: Michael Weghorn <m.weghorn@posteo.de>
> Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=28392
>
> Reviewed-By: Eli Zaretskii <eliz@gnu.org>
> Tested-By: Guinevere Larsen <guinevere@redhat.com>
Thanks for the detailed explanation. This makes sense to me.
I also tested this patch and found no problems.
Approved-by: Kevin Buettner <kevinb@redhat.com>
next prev parent reply other threads:[~2025-06-24 21:51 UTC|newest]
Thread overview: 10+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-05-13 10:31 Andrew Burgess
2025-06-24 21:50 ` Kevin Buettner [this message]
2025-09-12 10:13 ` Andrew Burgess
2025-09-16 8:55 ` Luis
2025-09-16 14:34 ` Andrew Burgess
2025-09-16 14:55 ` Andrew Burgess
2025-09-16 16:21 ` Andrew Burgess
2025-09-16 23:25 ` Luis
2025-09-17 0:19 ` Luis
2025-09-17 8:57 ` Andrew Burgess
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20250624145052.4659642b@f41-zbm-amd \
--to=kevinb@redhat.com \
--cc=aburgess@redhat.com \
--cc=eliz@gnu.org \
--cc=gdb-patches@sourceware.org \
--cc=guinevere@redhat.com \
--cc=m.weghorn@posteo.de \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox