[binutils-gdb] gdb/gdbserver: move argument setting complexity into gdbsupport/

Andrew Burgess aburgess@sourceware.org
Fri Feb 13 18:46:47 GMT 2026


https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=7de2cbde437a37aae1b8eb8da7718e5179187dda

commit 7de2cbde437a37aae1b8eb8da7718e5179187dda
Author: Andrew Burgess <aburgess@redhat.com>
Date:   Sun Nov 19 15:24:59 2023 +0000

    gdb/gdbserver: move argument setting complexity into gdbsupport/
    
    This commit removes some uses of gdb::argv_vec from GDB.
    
    The gdb::argv_vec class exists in part due to our need to convert from
    one container type to another in a few places, and I think by using
    templates we can push this conversion down into
    gdbsupport/common-inferior.{cc,h} and remove the conversion logic from
    higher level code in GDB.  This should make core GDB simpler.
    
    For examples of this simplification, see python/py-inferior.c,
    remote.c, and unittests/remote-arg-selftests.c, where this commit has
    allowed for the removal of some code that only exists in order to
    convert the container type.
    
    Ideally I'd like to see all uses of gdb::argv_vec removed, but I'm
    still not sure about the use in nat/fork-inferior.c, I think its use
    there might be the best solution, so for now at least, I have no plans
    to touch that code.
    
    There should be no user visible changes after this commit.
    
    Approved-By: Tom Tromey <tom@tromey.com>

Diff:
---
 gdb/inferior.c                       |  9 ------
 gdb/inferior.h                       |  7 +++-
 gdb/python/py-inferior.c             |  7 ++--
 gdb/remote.c                         | 13 ++------
 gdb/unittests/remote-arg-selftests.c |  6 +---
 gdbserver/server.cc                  | 20 ++++++------
 gdbsupport/common-inferior.cc        | 63 +++++++++++++++++++++++++++++++++---
 gdbsupport/common-inferior.h         | 11 +++++--
 gdbsupport/remote-args.cc            |  8 -----
 gdbsupport/remote-args.h             | 16 +++++++--
 10 files changed, 101 insertions(+), 59 deletions(-)

diff --git a/gdb/inferior.c b/gdb/inferior.c
index 438ed9b7d74..e050dec402e 100644
--- a/gdb/inferior.c
+++ b/gdb/inferior.c
@@ -165,15 +165,6 @@ inferior::tty ()
   return m_terminal;
 }
 
-/* See inferior.h.  */
-
-void
-inferior::set_args (gdb::array_view<char * const> args,
-		    bool escape_shell_char)
-{
-  set_args (construct_inferior_arguments (args, escape_shell_char));
-}
-
 void
 inferior::set_arch (gdbarch *arch)
 {
diff --git a/gdb/inferior.h b/gdb/inferior.h
index 4df80a0ff97..a3d4842be2c 100644
--- a/gdb/inferior.h
+++ b/gdb/inferior.h
@@ -62,6 +62,7 @@ struct thread_info;
 #include "displaced-stepping.h"
 
 #include "gdbsupport/unordered_map.h"
+#include "gdbsupport/common-inferior.h"
 
 struct infcall_suspend_state;
 struct infcall_control_state;
@@ -545,7 +546,11 @@ public:
      ESCAPE_SHELL_CHAR is true all special shell characters in ARGS are
      escaped, When false only the characters that GDB sees as special will
      be escaped.  See construct_inferior_arguments for more details.  */
-  void set_args (gdb::array_view<char * const> args, bool escape_shell_char);
+  template<typename T>
+  void set_args (gdb::array_view<T const> args, bool escape_shell_char)
+  {
+    this->set_args (construct_inferior_arguments (args, escape_shell_char));
+  }
 
   /* Get the argument string to use when running this inferior.
 
diff --git a/gdb/python/py-inferior.c b/gdb/python/py-inferior.c
index 69a7bfa3c37..53f3344429d 100644
--- a/gdb/python/py-inferior.c
+++ b/gdb/python/py-inferior.c
@@ -905,11 +905,8 @@ infpy_set_args (PyObject *self, PyObject *value, void *closure)
 	    return -1;
 	  args.push_back (std::move (str));
 	}
-      std::vector<char *> argvec;
-      for (const auto &arg : args)
-	argvec.push_back (arg.get ());
-      gdb::array_view<char * const> view (argvec.data (), argvec.size ());
-      inf->inferior->set_args (view, true);
+      gdb::array_view<gdb::unique_xmalloc_ptr<char> const> args_view (args);
+      inf->inferior->set_args (args_view, true);
     }
   else
     {
diff --git a/gdb/remote.c b/gdb/remote.c
index edabc2c9ee5..4ad595bda68 100644
--- a/gdb/remote.c
+++ b/gdb/remote.c
@@ -83,7 +83,6 @@
 #include "gdbsupport/selftest.h"
 #include "cli/cli-style.h"
 #include "gdbsupport/remote-args.h"
-#include "gdbsupport/gdb_argv_vec.h"
 #include "finish-thread-state.h"
 
 /* The remote target.  */
@@ -12761,21 +12760,13 @@ test_remote_args_command (const char *args, int from_tty)
   for (const std::string &a : split_args)
     gdb_printf ("  (%s)\n", a.c_str ());
 
-  gdb::argv_vec tmp_split_args;
-  for (const std::string &a : split_args)
-    tmp_split_args.emplace_back (xstrdup (a.c_str ()));
-
-  std::string joined_args = gdb::remote_args::join (tmp_split_args.get ());
+  std::string joined_args = gdb::remote_args::join (split_args);
 
   gdb_printf ("Output (%s)\n", joined_args.c_str ());
 
   std::vector<std::string> resplit = gdb::remote_args::split (joined_args);
 
-  tmp_split_args.clear ();
-  for (const std::string &a : resplit)
-    tmp_split_args.emplace_back (xstrdup (a.c_str ()));
-
-  std::string rejoined = gdb::remote_args::join (tmp_split_args.get ());
+  std::string rejoined = gdb::remote_args::join (resplit);
 
   if (joined_args != rejoined || split_args != resplit)
     {
diff --git a/gdb/unittests/remote-arg-selftests.c b/gdb/unittests/remote-arg-selftests.c
index ec0678b46d8..e878fefb2ef 100644
--- a/gdb/unittests/remote-arg-selftests.c
+++ b/gdb/unittests/remote-arg-selftests.c
@@ -22,7 +22,6 @@
 #include "gdbsupport/buildargv.h"
 #include "gdbsupport/common-inferior.h"
 #include "gdbsupport/remote-args.h"
-#include "gdbsupport/gdb_argv_vec.h"
 
 namespace selftests {
 namespace remote_args_tests {
@@ -107,11 +106,8 @@ self_test ()
 	}
 
       /* Now join the arguments.  */
-      gdb::argv_vec split_args_c_str;
-      for (const std::string &s : split_args)
-	split_args_c_str.push_back (xstrdup (s.c_str ()));
       std::string joined_args
-	= gdb::remote_args::join (split_args_c_str.get ());
+	= gdb::remote_args::join (split_args);
 
       if (run_verbose ())
 	debug_printf ("Joined (%s), expected (%s)\n",
diff --git a/gdbserver/server.cc b/gdbserver/server.cc
index 674300f8ce0..a7ecef3f5aa 100644
--- a/gdbserver/server.cc
+++ b/gdbserver/server.cc
@@ -49,7 +49,6 @@
 #include "gdbsupport/gdb_select.h"
 #include "gdbsupport/scoped_restore.h"
 #include "gdbsupport/search.h"
-#include "gdbsupport/gdb_argv_vec.h"
 #include "gdbsupport/remote-args.h"
 
 #include <getopt.h>
@@ -3442,7 +3441,7 @@ handle_v_run (char *own_buf)
 {
   client_state &cs = get_client_state ();
   char *p, *next_p;
-  gdb::argv_vec new_argv;
+  std::vector<gdb::unique_xmalloc_ptr<char>> new_argv;
   gdb::unique_xmalloc_ptr<char> new_program_name;
   int i;
 
@@ -3462,7 +3461,7 @@ handle_v_run (char *own_buf)
       else if (p == next_p)
 	{
 	  /* Empty argument.  */
-	  new_argv.push_back (xstrdup (""));
+	  new_argv.push_back (make_unique_xstrdup (""));
 	}
       else
 	{
@@ -3479,7 +3478,7 @@ handle_v_run (char *own_buf)
 	  if (i == 0)
 	    new_program_name = std::move (arg);
 	  else
-	    new_argv.push_back (arg.release ());
+	    new_argv.push_back (std::move (arg));
 	}
       if (*next_p == '\0')
 	break;
@@ -3500,18 +3499,18 @@ handle_v_run (char *own_buf)
 
   if (cs.single_inferior_argument)
     {
-      if (new_argv.get ().size () > 1)
+      if (new_argv.size () > 1)
 	{
 	  write_enn (own_buf);
 	  return;
 	}
-      else if (new_argv.get ().size () == 1)
-	program_args = std::string (new_argv.get ()[0]);
+      else if (new_argv.size () == 1)
+	program_args = std::string (new_argv[0].get ());
       else
 	program_args.clear ();
     }
   else
-    program_args = gdb::remote_args::join (new_argv.get ());
+    program_args = gdb::remote_args::join (new_argv);
 
   try
     {
@@ -4579,9 +4578,8 @@ captured_main (int argc, char *argv[])
 	error (_("No program to debug"));
 
       int n = argc - (next_arg - argv);
-      program_args
-	= construct_inferior_arguments ({&next_arg[1], &next_arg[n]},
-					escape_args);
+      gdb::array_view<char * const> args_view (&next_arg[1], &next_arg[n]);
+      program_args = construct_inferior_arguments (args_view, escape_args);
 
       /* Wait till we are at first instruction in program.  */
       target_create_inferior (program_path.get (), program_args);
diff --git a/gdbsupport/common-inferior.cc b/gdbsupport/common-inferior.cc
index 11b59210068..8134761ef73 100644
--- a/gdbsupport/common-inferior.cc
+++ b/gdbsupport/common-inferior.cc
@@ -130,10 +130,43 @@ escape_gdb_characters (const char * arg)
   return escape_characters (arg, special);
 }
 
-/* See common-inferior.h.  */
+/* Template function that converts a T to a 'const char *'.  */
+
+template<typename T> const char * to_char_ptr (T &arg);
+
+/* A no-op implementation that takes a 'const char *'.  */
+
+template<>
+const char *
+to_char_ptr (char * const &arg)
+{
+  return arg;
+}
+
+/* An implementation that gets a 'const char *' from a
+   gdb::unique_xmalloc_ptr<char> object.  */
+
+template<>
+const char *
+to_char_ptr (const gdb::unique_xmalloc_ptr<char> &arg)
+{
+  return arg.get ();
+}
+
+/* An implementation that gets a 'const char *' from a std::string.  */
+
+template<>
+const char *
+to_char_ptr (const std::string &arg)
+{
+  return arg.c_str ();
+}
+
+/* See gdbsupport/common-inferior.h.  */
 
+template<typename T>
 std::string
-construct_inferior_arguments (gdb::array_view<char * const> argv,
+construct_inferior_arguments (gdb::array_view<T const> argv,
 			      bool escape_shell_char)
 {
   /* Select the desired escape function.  */
@@ -143,13 +176,35 @@ construct_inferior_arguments (gdb::array_view<char * const> argv,
 
   std::string result;
 
-  for (const char *a : argv)
+  for (const T &a : argv)
     {
       if (!result.empty ())
 	result += " ";
 
-      result += escape_func (a);
+      result += escape_func (to_char_ptr (a));
     }
 
   return result;
 }
+
+/* Instantiate for T = 'gdb::unique_xmalloc_ptr<char>'.  */
+
+template
+std::string
+construct_inferior_arguments
+  (gdb::array_view<gdb::unique_xmalloc_ptr<char> const> argv,
+   bool escape_shell_char);
+
+/* Instantiate for T = 'char *'.  */
+
+template
+std::string
+construct_inferior_arguments (gdb::array_view<char * const> argv,
+			      bool escape_shell_char);
+
+/* Instantiate for T = 'std::string'.  */
+
+template
+std::string
+construct_inferior_arguments (gdb::array_view<std::string const> argv,
+			      bool escape_shell_char);
diff --git a/gdbsupport/common-inferior.h b/gdbsupport/common-inferior.h
index b48f72ed152..4645119e451 100644
--- a/gdbsupport/common-inferior.h
+++ b/gdbsupport/common-inferior.h
@@ -56,9 +56,14 @@ extern bool startup_with_shell;
    whitespace character between each element.  When ESCAPE_SHELL_CHAR is
    true then any special shell characters in elements of ARGV will be
    escaped.  When ESCAPE_SHELL_CHAR is false only the characters that GDB
-   sees as special (quotes and whitespace) are escaped.  */
+   sees as special (quotes and whitespace) are escaped.
+
+   This function is instantiated for T as 'gdb::unique_xmalloc_ptr<char>',
+   'char *', and 'std::string'.  */
+
+template<typename T>
 extern std::string
-construct_inferior_arguments (gdb::array_view<char * const> argv,
-			      bool escape_shell_char);
+construct_inferior_arguments
+	(gdb::array_view<T const> argv, bool escape_shell_char);
 
 #endif /* GDBSUPPORT_COMMON_INFERIOR_H */
diff --git a/gdbsupport/remote-args.cc b/gdbsupport/remote-args.cc
index 3e8fc903f6f..232adbff998 100644
--- a/gdbsupport/remote-args.cc
+++ b/gdbsupport/remote-args.cc
@@ -33,11 +33,3 @@ gdb::remote_args::split (const std::string &args)
 
   return results;
 }
-
-/* See remote-args.h.  */
-
-std::string
-gdb::remote_args::join (const std::vector<char *> &args)
-{
-  return construct_inferior_arguments (args, true);
-}
diff --git a/gdbsupport/remote-args.h b/gdbsupport/remote-args.h
index 2a925e889a4..d714702a9b8 100644
--- a/gdbsupport/remote-args.h
+++ b/gdbsupport/remote-args.h
@@ -20,6 +20,8 @@
 #ifndef GDBSUPPORT_REMOTE_ARGS_H
 #define GDBSUPPORT_REMOTE_ARGS_H
 
+#include "gdbsupport/common-inferior.h"
+
 /* The functions declared here are used when passing inferior arguments
    from GDB to gdbserver.
 
@@ -50,8 +52,18 @@ extern std::vector<std::string> split (const std::string &args);
    argument of 'a b' (without the single quotes).  When this argument is
    passed through ::join we will get back the string 'a\ b' (without the
    single quotes), that is, we choose to escape the white space, rather
-   than wrap the argument in quotes.  */
-extern std::string join (const std::vector<char *> &args);
+   than wrap the argument in quotes.
+
+   This function depends on construct_inferior_arguments, which is
+   instantiated for the string types used within GDB, 'char *',
+   'std::string', and 'gdb::unique_xmalloc_ptr<char>'.  */
+
+template<typename T>
+inline std::string
+join (const std::vector<T> &args)
+{
+  return construct_inferior_arguments (gdb::array_view<const T> (args), true);
+}
 
 } /* namespace remote_args */


More information about the Gdb-cvs mailing list