mirror of
https://github.com/bminor/binutils-gdb.git
synced 2025-11-16 12:34:43 +00:00
gdb: new maintenance command to help debug remote argument issues
Add a new maintenance command 'maint test-remote-args', this command takes an argument string and splits it using gdb::remote_args::split and then joins the result using gdb::remote_args::join and prints all of the results. This is useful for diagnosing problems with remote argument passing. This new command is identical to what the remote argument self-tests do, but while I was working on improving remote argument passing it was far easier to have a command that I could just throw example strings at, rather than having to add new selftests and recompile GDB. I ended up adding a couple of additional helper functions to the gdb::argv_vec class. Reviewed-By: Eli Zaretskii <eliz@gnu.org> Tested-By: Guinevere Larsen <guinevere@redhat.com> Approved-By: Kevin Buettner <kevinb@redhat.com>
This commit is contained in:
6
gdb/NEWS
6
gdb/NEWS
@@ -18,6 +18,12 @@
|
|||||||
|
|
||||||
GNU/Linux/MicroBlaze (gdbserver) microblazeel-*linux*
|
GNU/Linux/MicroBlaze (gdbserver) microblazeel-*linux*
|
||||||
|
|
||||||
|
* New commands
|
||||||
|
|
||||||
|
maintenance test-remote-args ARGS
|
||||||
|
Test splitting and joining of inferior arguments ARGS as they would
|
||||||
|
be split and joined when being passed to a remote target.
|
||||||
|
|
||||||
* Changed remote packets
|
* Changed remote packets
|
||||||
|
|
||||||
single-inf-arg in qSupported
|
single-inf-arg in qSupported
|
||||||
|
|||||||
@@ -42842,6 +42842,26 @@ These are representative commands for each @var{kind} of setting type
|
|||||||
@value{GDBN} supports. They are used by the testsuite for exercising
|
@value{GDBN} supports. They are used by the testsuite for exercising
|
||||||
the settings infrastructure.
|
the settings infrastructure.
|
||||||
|
|
||||||
|
@kindex maint test-remote-args
|
||||||
|
@item maint test-remote-args @var{args}
|
||||||
|
For targets that don't support passing inferior arguments as a single
|
||||||
|
string (@pxref{single-inf-arg}), @value{GDBN} will attempt to split
|
||||||
|
the inferior arguments before passing them to the remote target, and
|
||||||
|
the remote target might choose to join the inferior arguments upon
|
||||||
|
receipt. Historically gdbserver did join inferior arguments, but now
|
||||||
|
it will request inferior arguments be passed as a single string if
|
||||||
|
@value{GDBN} supports this feature.
|
||||||
|
|
||||||
|
This maintenance command splits @var{args} as @value{GDBN} would
|
||||||
|
normally split such an argument string before passing the arguments to
|
||||||
|
a remote target, the split arguments are then printed.
|
||||||
|
|
||||||
|
The split arguments are then joined together as gdbserver would join
|
||||||
|
them, and the result is printed.
|
||||||
|
|
||||||
|
This command is intended to help diagnose issues passing inferior
|
||||||
|
arguments to remote targets.
|
||||||
|
|
||||||
@kindex maint set backtrace-on-fatal-signal
|
@kindex maint set backtrace-on-fatal-signal
|
||||||
@kindex maint show backtrace-on-fatal-signal
|
@kindex maint show backtrace-on-fatal-signal
|
||||||
@item maint set backtrace-on-fatal-signal [on|off]
|
@item maint set backtrace-on-fatal-signal [on|off]
|
||||||
|
|||||||
60
gdb/remote.c
60
gdb/remote.c
@@ -81,6 +81,7 @@
|
|||||||
#include "gdbsupport/selftest.h"
|
#include "gdbsupport/selftest.h"
|
||||||
#include "cli/cli-style.h"
|
#include "cli/cli-style.h"
|
||||||
#include "gdbsupport/remote-args.h"
|
#include "gdbsupport/remote-args.h"
|
||||||
|
#include "gdbsupport/gdb_argv_vec.h"
|
||||||
|
|
||||||
/* The remote target. */
|
/* The remote target. */
|
||||||
|
|
||||||
@@ -12278,6 +12279,51 @@ cli_packet_command (const char *args, int from_tty)
|
|||||||
send_remote_packet (view, &cb);
|
send_remote_packet (view, &cb);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Implement 'maint test-remote-args' command.
|
||||||
|
|
||||||
|
Treat ARGS as an argument string. Split the remote arguments using
|
||||||
|
gdb::remote_args::split, and then join using gdb::remote_args::join.
|
||||||
|
The split and joined arguments are printed out. Additionally, the
|
||||||
|
joined arguments are split and joined a second time, and compared to the
|
||||||
|
result of the first join, this provides some basic validation that GDB
|
||||||
|
sess the joined arguments as equivalent to the original argument
|
||||||
|
string. */
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_remote_args_command (const char *args, int from_tty)
|
||||||
|
{
|
||||||
|
std::vector<std::string> split_args = gdb::remote_args::split (args);
|
||||||
|
|
||||||
|
gdb_printf ("Input (%s)\n", args);
|
||||||
|
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 ());
|
||||||
|
|
||||||
|
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 ());
|
||||||
|
|
||||||
|
if (joined_args != rejoined || split_args != resplit)
|
||||||
|
{
|
||||||
|
gdb_printf ("FAILURE ON REJOINING\n");
|
||||||
|
gdb_printf ("Resplit args:\n");
|
||||||
|
for (const auto & a : resplit)
|
||||||
|
gdb_printf (" (%s)\n", a.c_str ());
|
||||||
|
gdb_printf ("Rejoined (%s)\n", rejoined.c_str ());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
/* --------- UNIT_TEST for THREAD oriented PACKETS ------------------- */
|
/* --------- UNIT_TEST for THREAD oriented PACKETS ------------------- */
|
||||||
|
|
||||||
@@ -16726,6 +16772,20 @@ from the target."),
|
|||||||
/* Eventually initialize fileio. See fileio.c */
|
/* Eventually initialize fileio. See fileio.c */
|
||||||
initialize_remote_fileio (&remote_set_cmdlist, &remote_show_cmdlist);
|
initialize_remote_fileio (&remote_set_cmdlist, &remote_show_cmdlist);
|
||||||
|
|
||||||
|
add_cmd ("test-remote-args", class_maintenance,
|
||||||
|
test_remote_args_command, _("\
|
||||||
|
Test remote argument splitting and joining.\n \
|
||||||
|
maintenance test-remote-args ARGS\n\
|
||||||
|
For remote targets that don't support passing inferior arguments as a\n\
|
||||||
|
single string, GDB needs to split the inferior arguments before passing\n\
|
||||||
|
them, and gdbserver needs to join the arguments it receives.\n\
|
||||||
|
This command splits ARGS just as GDB would before passing them to a\n\
|
||||||
|
remote target, and prints the result. This command then joins the\n\
|
||||||
|
arguments just as gdbserver would, and prints the results.\n\
|
||||||
|
This command is useful in diagnosing problems when passing arguments\n\
|
||||||
|
between GDB and a remote target."),
|
||||||
|
&maintenancelist);
|
||||||
|
|
||||||
#if GDB_SELF_TEST
|
#if GDB_SELF_TEST
|
||||||
selftests::register_test ("remote_memory_tagging",
|
selftests::register_test ("remote_memory_tagging",
|
||||||
selftests::test_memory_tagging_functions);
|
selftests::test_memory_tagging_functions);
|
||||||
|
|||||||
40
gdb/testsuite/gdb.base/maint-test-remote-args.exp
Normal file
40
gdb/testsuite/gdb.base/maint-test-remote-args.exp
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
# Copyright 2024-2025 Free Software Foundation, Inc.
|
||||||
|
#
|
||||||
|
# This program is free software; you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation; either version 3 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
# Test the 'maint test-remote-args' command.
|
||||||
|
#
|
||||||
|
# We do minimal testing in here. If you are thinking of adding a new
|
||||||
|
# test here then you are most likely adding the test in the wrong
|
||||||
|
# place. Remote argument testing is checked in the following test
|
||||||
|
# scripts: gdb.base/args.exp, gdb.base/inferior-args.exp,
|
||||||
|
# gdb.base/startup-with-shell.exp, and gdb.python/py-inferior.exp.
|
||||||
|
# The test gdb.gdb/unittest.exp also runs 'maint selftest
|
||||||
|
# remote-args', which are the remote argument self tests.
|
||||||
|
#
|
||||||
|
# If you have a new test for an argument that was being passed
|
||||||
|
# incorrectly, then add the test to one of those scripts.
|
||||||
|
#
|
||||||
|
# This file is ONLY for validating that the 'maint test-remote-args'
|
||||||
|
# command itself is working.
|
||||||
|
|
||||||
|
gdb_start
|
||||||
|
|
||||||
|
gdb_test "maint test-remote-args a b c" \
|
||||||
|
[multi_line \
|
||||||
|
"Input \\(a b c\\)" \
|
||||||
|
" \\(a\\)" \
|
||||||
|
" \\(b\\)" \
|
||||||
|
" \\(c\\)" \
|
||||||
|
"Output \\(a b c\\)"]
|
||||||
@@ -90,6 +90,15 @@ public:
|
|||||||
m_args.push_back (value);
|
m_args.push_back (value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Like calling emplace_back on the underlying vector. This class takes
|
||||||
|
ownership of the value added to the vector, and will release the value
|
||||||
|
by calling xfree() on it when this object is destroyed. */
|
||||||
|
template<typename... Args>
|
||||||
|
reference emplace_back (Args &&...args)
|
||||||
|
{
|
||||||
|
return m_args.emplace_back (std::forward<Args> (args)...);
|
||||||
|
}
|
||||||
|
|
||||||
/* Non constant iterator to start of m_args. */
|
/* Non constant iterator to start of m_args. */
|
||||||
iterator begin ()
|
iterator begin ()
|
||||||
{
|
{
|
||||||
@@ -133,6 +142,12 @@ public:
|
|||||||
{
|
{
|
||||||
return m_args.empty ();
|
return m_args.empty ();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Clear the argument vector. */
|
||||||
|
void clear ()
|
||||||
|
{
|
||||||
|
free_vector_argv (m_args);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
} /* namespac gdb */
|
} /* namespac gdb */
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user