* [PATCH v3 0/3] gdbstub: avoid untimely stop-reply msgs
@ 2022-09-20 12:47 Matheus Tavares Bernardino
2022-09-20 12:47 ` [PATCH v3 1/3] configure: make sure tcg tests can see HAVE_GDB_BIN Matheus Tavares Bernardino
` (2 more replies)
0 siblings, 3 replies; 4+ messages in thread
From: Matheus Tavares Bernardino @ 2022-09-20 12:47 UTC (permalink / raw)
To: qemu-devel; +Cc: bcain, alex.bennee, f4bug, peter.maydell
This series limits gdbstub to send stop-reply packets only as a reply to
commands that accept them, following the RSP specification.
Changes since v2[1]:
- Replaced char buffer with boolean at struct GDBState.
- Covered other functions that might send stop-reply packets.
- Added test.
Note: I was able to run the added test previously I make sure it passes
after the change, but after rebasing onto master, `make check-tcg` is
giving me the following error (this also happens at the tip of master in
my machine):
qemu: could not load PC BIOS 'bios-256k.bin'
Perhaps I'm doing something wrong at compilation/testing?
[1]: https://lore.kernel.org/qemu-devel/ba99db564c3aeb1812bdfbc9116849092334482f.1661362557.git.quic_mathbern@quicinc.com/
Matheus Tavares Bernardino (3):
configure: make sure tcg tests can see HAVE_GDB_BIN
gdbstub: only send stop-reply packets when allowed to
gdbstub: add test for untimely stop-reply packets
configure | 13 ++--
gdbstub.c | 64 ++++++++++++++-----
meson.build | 6 +-
tests/guest-debug/run-test.py | 16 +++--
.../multiarch/system/Makefile.softmmu-target | 16 ++++-
5 files changed, 83 insertions(+), 32 deletions(-)
--
2.37.2
^ permalink raw reply [flat|nested] 4+ messages in thread
* [PATCH v3 1/3] configure: make sure tcg tests can see HAVE_GDB_BIN
2022-09-20 12:47 [PATCH v3 0/3] gdbstub: avoid untimely stop-reply msgs Matheus Tavares Bernardino
@ 2022-09-20 12:47 ` Matheus Tavares Bernardino
2022-09-20 12:47 ` [PATCH v3 2/3] gdbstub: only send stop-reply packets when allowed to Matheus Tavares Bernardino
2022-09-20 12:47 ` [PATCH v3 3/3] gdbstub: add test for untimely stop-reply packets Matheus Tavares Bernardino
2 siblings, 0 replies; 4+ messages in thread
From: Matheus Tavares Bernardino @ 2022-09-20 12:47 UTC (permalink / raw)
To: qemu-devel; +Cc: bcain, alex.bennee, f4bug, peter.maydell
HAVE_GDB_BIN is only used by tests/tcg/* makefiles, but it is currently
written at <build_dir>/config-host.mak, which those makefiles don't have
access to. Let's instead write it to
<build_dir>/tests/tcg/config-host.mak, which is included by the
makefiles.
Signed-off-by: Matheus Tavares Bernardino <quic_mathbern@quicinc.com>
---
configure | 13 ++++++-------
meson.build | 6 +++---
2 files changed, 9 insertions(+), 10 deletions(-)
diff --git a/configure b/configure
index 575dde1c1f..e9dc766467 100755
--- a/configure
+++ b/configure
@@ -2474,13 +2474,6 @@ if test "$plugins" = "yes" ; then
echo "CONFIG_PLUGIN=y" >> $config_host_mak
fi
-if test -n "$gdb_bin"; then
- gdb_version=$($gdb_bin --version | head -n 1)
- if version_ge ${gdb_version##* } 9.1; then
- echo "HAVE_GDB_BIN=$gdb_bin" >> $config_host_mak
- fi
-fi
-
echo "ROMS=$roms" >> $config_host_mak
echo "MAKE=$make" >> $config_host_mak
echo "PYTHON=$python" >> $config_host_mak
@@ -2561,6 +2554,12 @@ config_host_mak=tests/tcg/config-host.mak
echo "# Automatically generated by configure - do not modify" > $config_host_mak
echo "SRC_PATH=$source_path" >> $config_host_mak
echo "HOST_CC=$host_cc" >> $config_host_mak
+if test -n "$gdb_bin"; then
+ gdb_version=$($gdb_bin --version | head -n 1)
+ if version_ge ${gdb_version##* } 9.1; then
+ echo "HAVE_GDB_BIN=$gdb_bin" >> $config_host_mak
+ fi
+fi
tcg_tests_targets=
for target in $target_list; do
diff --git a/meson.build b/meson.build
index c2adb7caf4..1a4ac4bc60 100644
--- a/meson.build
+++ b/meson.build
@@ -3710,9 +3710,6 @@ summary_info += {'git': config_host['GIT']}
summary_info += {'make': config_host['MAKE']}
summary_info += {'python': '@0@ (version: @1@)'.format(python.full_path(), python.language_version())}
summary_info += {'sphinx-build': sphinx_build}
-if config_host.has_key('HAVE_GDB_BIN')
- summary_info += {'gdb': config_host['HAVE_GDB_BIN']}
-endif
summary_info += {'iasl': iasl}
summary_info += {'genisoimage': config_host['GENISOIMAGE']}
if targetos == 'windows' and have_ga
@@ -3822,6 +3819,9 @@ foreach target: target_dirs
summary_info += {config_cross_tcg['TARGET_NAME']: config_cross_tcg['CC']}
have_cross = true
endif
+ if config_cross_tcg.has_key('HAVE_GDB_BIN')
+ summary_info += {'gdb': config_cross_tcg['HAVE_GDB_BIN']}
+ endif
endif
endforeach
if have_cross
--
2.37.2
^ permalink raw reply related [flat|nested] 4+ messages in thread
* [PATCH v3 2/3] gdbstub: only send stop-reply packets when allowed to
2022-09-20 12:47 [PATCH v3 0/3] gdbstub: avoid untimely stop-reply msgs Matheus Tavares Bernardino
2022-09-20 12:47 ` [PATCH v3 1/3] configure: make sure tcg tests can see HAVE_GDB_BIN Matheus Tavares Bernardino
@ 2022-09-20 12:47 ` Matheus Tavares Bernardino
2022-09-20 12:47 ` [PATCH v3 3/3] gdbstub: add test for untimely stop-reply packets Matheus Tavares Bernardino
2 siblings, 0 replies; 4+ messages in thread
From: Matheus Tavares Bernardino @ 2022-09-20 12:47 UTC (permalink / raw)
To: qemu-devel; +Cc: bcain, alex.bennee, f4bug, peter.maydell
GDB's remote serial protocol allows stop-reply messages to be sent by
the stub either as a notification packet or as a reply to a GDB command
(provided that the cmd accepts such a response). QEMU currently does not
implement notification packets, so it should only send stop-replies
synchronously and when requested. Nevertheless, it may still issue
unsolicited stop messages through gdb_vm_state_change().
Although this behavior doesn't seem to cause problems with GDB itself,
it does with other debuggers that implement the GDB remote serial
protocol, like hexagon-lldb. In this case, the debugger fails upon an
unexpected stop-reply message from QEMU when lldb attaches to it.
Instead, let's change the gdbstub to send stop messages only as a
response to a previous GDB command that accepts such a reply.
Signed-off-by: Matheus Tavares Bernardino <quic_mathbern@quicinc.com>
---
gdbstub.c | 64 ++++++++++++++++++++++++++++++++++++++++---------------
1 file changed, 47 insertions(+), 17 deletions(-)
diff --git a/gdbstub.c b/gdbstub.c
index cf869b10e3..14b4348c18 100644
--- a/gdbstub.c
+++ b/gdbstub.c
@@ -369,6 +369,7 @@ typedef struct GDBState {
GByteArray *mem_buf;
int sstep_flags;
int supported_sstep_flags;
+ bool allow_stop_reply;
} GDBState;
static GDBState gdbserver_state;
@@ -412,6 +413,7 @@ static void reset_gdbserver_state(void)
g_free(gdbserver_state.processes);
gdbserver_state.processes = NULL;
gdbserver_state.process_num = 0;
+ gdbserver_state.allow_stop_reply = 0;
}
#endif
@@ -1484,6 +1486,7 @@ typedef struct GdbCmdParseEntry {
const char *cmd;
bool cmd_startswith;
const char *schema;
+ bool allow_stop_reply;
} GdbCmdParseEntry;
static inline int startswith(const char *string, const char *pattern)
@@ -1517,6 +1520,7 @@ static int process_string_cmd(void *user_ctx, const char *data,
}
}
+ gdbserver_state.allow_stop_reply = cmd->allow_stop_reply;
cmd->handler(params, user_ctx);
return 0;
}
@@ -2013,11 +2017,14 @@ static void handle_v_attach(GArray *params, void *user_ctx)
gdbserver_state.g_cpu = cpu;
gdbserver_state.c_cpu = cpu;
- g_string_printf(gdbserver_state.str_buf, "T%02xthread:", GDB_SIGNAL_TRAP);
- gdb_append_thread_id(cpu, gdbserver_state.str_buf);
- g_string_append_c(gdbserver_state.str_buf, ';');
+ if (gdbserver_state.allow_stop_reply) {
+ g_string_printf(gdbserver_state.str_buf, "T%02xthread:", GDB_SIGNAL_TRAP);
+ gdb_append_thread_id(cpu, gdbserver_state.str_buf);
+ g_string_append_c(gdbserver_state.str_buf, ';');
+ gdbserver_state.allow_stop_reply = 0;
cleanup:
- put_strbuf();
+ put_strbuf();
+ }
}
static void handle_v_kill(GArray *params, void *user_ctx)
@@ -2040,12 +2047,14 @@ static const GdbCmdParseEntry gdb_v_commands_table[] = {
.handler = handle_v_cont,
.cmd = "Cont",
.cmd_startswith = 1,
+ .allow_stop_reply = 1,
.schema = "s0"
},
{
.handler = handle_v_attach,
.cmd = "Attach;",
.cmd_startswith = 1,
+ .allow_stop_reply = 1,
.schema = "l0"
},
{
@@ -2546,10 +2555,13 @@ static void handle_gen_set(GArray *params, void *user_ctx)
static void handle_target_halt(GArray *params, void *user_ctx)
{
- g_string_printf(gdbserver_state.str_buf, "T%02xthread:", GDB_SIGNAL_TRAP);
- gdb_append_thread_id(gdbserver_state.c_cpu, gdbserver_state.str_buf);
- g_string_append_c(gdbserver_state.str_buf, ';');
- put_strbuf();
+ if (gdbserver_state.allow_stop_reply) {
+ g_string_printf(gdbserver_state.str_buf, "T%02xthread:", GDB_SIGNAL_TRAP);
+ gdb_append_thread_id(gdbserver_state.c_cpu, gdbserver_state.str_buf);
+ g_string_append_c(gdbserver_state.str_buf, ';');
+ put_strbuf();
+ gdbserver_state.allow_stop_reply = 0;
+ }
/*
* Remove all the breakpoints when this query is issued,
* because gdb is doing an initial connect and the state
@@ -2573,7 +2585,8 @@ static int gdb_handle_packet(const char *line_buf)
static const GdbCmdParseEntry target_halted_cmd_desc = {
.handler = handle_target_halt,
.cmd = "?",
- .cmd_startswith = 1
+ .cmd_startswith = 1,
+ .allow_stop_reply = 1,
};
cmd_parser = &target_halted_cmd_desc;
}
@@ -2584,6 +2597,7 @@ static int gdb_handle_packet(const char *line_buf)
.handler = handle_continue,
.cmd = "c",
.cmd_startswith = 1,
+ .allow_stop_reply = 1,
.schema = "L0"
};
cmd_parser = &continue_cmd_desc;
@@ -2595,6 +2609,7 @@ static int gdb_handle_packet(const char *line_buf)
.handler = handle_cont_with_sig,
.cmd = "C",
.cmd_startswith = 1,
+ .allow_stop_reply = 1,
.schema = "l0"
};
cmd_parser = &cont_with_sig_cmd_desc;
@@ -2633,6 +2648,7 @@ static int gdb_handle_packet(const char *line_buf)
.handler = handle_step,
.cmd = "s",
.cmd_startswith = 1,
+ .allow_stop_reply = 1,
.schema = "L0"
};
cmd_parser = &step_cmd_desc;
@@ -2843,6 +2859,10 @@ static void gdb_vm_state_change(void *opaque, bool running, RunState state)
return;
}
+ if (!gdbserver_state.allow_stop_reply) {
+ return;
+ }
+
gdb_append_thread_id(cpu, tid);
switch (state) {
@@ -2908,6 +2928,7 @@ static void gdb_vm_state_change(void *opaque, bool running, RunState state)
send_packet:
put_packet(buf->str);
+ gdbserver_state.allow_stop_reply = 0;
/* disable single step if it was enabled */
cpu_single_step(cpu, 0);
@@ -3000,6 +3021,7 @@ static void gdb_read_byte(uint8_t ch)
{
uint8_t reply;
+ gdbserver_state.allow_stop_reply = 0;
#ifndef CONFIG_USER_ONLY
if (gdbserver_state.last_packet->len) {
/* Waiting for a response to the last packet. If we see the start
@@ -3162,8 +3184,11 @@ void gdb_exit(int code)
trace_gdbstub_op_exiting((uint8_t)code);
- snprintf(buf, sizeof(buf), "W%02x", (uint8_t)code);
- put_packet(buf);
+ if (gdbserver_state.allow_stop_reply) {
+ snprintf(buf, sizeof(buf), "W%02x", (uint8_t)code);
+ put_packet(buf);
+ gdbserver_state.allow_stop_reply = 0;
+ }
#ifndef CONFIG_USER_ONLY
qemu_chr_fe_deinit(&gdbserver_state.chr, true);
@@ -3212,11 +3237,14 @@ gdb_handlesig(CPUState *cpu, int sig)
if (sig != 0) {
gdb_set_stop_cpu(cpu);
- g_string_printf(gdbserver_state.str_buf,
- "T%02xthread:", target_signal_to_gdb(sig));
- gdb_append_thread_id(cpu, gdbserver_state.str_buf);
- g_string_append_c(gdbserver_state.str_buf, ';');
- put_strbuf();
+ if (gdbserver_state.allow_stop_reply) {
+ g_string_printf(gdbserver_state.str_buf,
+ "T%02xthread:", target_signal_to_gdb(sig));
+ gdb_append_thread_id(cpu, gdbserver_state.str_buf);
+ g_string_append_c(gdbserver_state.str_buf, ';');
+ put_strbuf();
+ gdbserver_state.allow_stop_reply = 0;
+ }
}
/* put_packet() might have detected that the peer terminated the
connection. */
@@ -3255,12 +3283,14 @@ void gdb_signalled(CPUArchState *env, int sig)
{
char buf[4];
- if (!gdbserver_state.init || gdbserver_state.fd < 0) {
+ if (!gdbserver_state.init || gdbserver_state.fd < 0 ||
+ !gdbserver_state.allow_stop_reply) {
return;
}
snprintf(buf, sizeof(buf), "X%02x", target_signal_to_gdb(sig));
put_packet(buf);
+ gdbserver_state.allow_stop_reply = 0;
}
static void gdb_accept_init(int fd)
--
2.37.2
^ permalink raw reply related [flat|nested] 4+ messages in thread
* [PATCH v3 3/3] gdbstub: add test for untimely stop-reply packets
2022-09-20 12:47 [PATCH v3 0/3] gdbstub: avoid untimely stop-reply msgs Matheus Tavares Bernardino
2022-09-20 12:47 ` [PATCH v3 1/3] configure: make sure tcg tests can see HAVE_GDB_BIN Matheus Tavares Bernardino
2022-09-20 12:47 ` [PATCH v3 2/3] gdbstub: only send stop-reply packets when allowed to Matheus Tavares Bernardino
@ 2022-09-20 12:47 ` Matheus Tavares Bernardino
2 siblings, 0 replies; 4+ messages in thread
From: Matheus Tavares Bernardino @ 2022-09-20 12:47 UTC (permalink / raw)
To: qemu-devel; +Cc: bcain, alex.bennee, f4bug, peter.maydell
In the previous commit, we modified gdbstub.c to only send stop-reply
packets as a response to GDB commands that accept it. Now, let's add a
test for this intended behavior. Running this test before the fix from
the previous commit fails as QEMU sends a stop-reply packet
asynchronously, when GDB was in fact waiting an ACK.
Signed-off-by: Matheus Tavares Bernardino <quic_mathbern@quicinc.com>
---
tests/guest-debug/run-test.py | 16 ++++++++++++----
.../tcg/multiarch/system/Makefile.softmmu-target | 16 +++++++++++++++-
2 files changed, 27 insertions(+), 5 deletions(-)
diff --git a/tests/guest-debug/run-test.py b/tests/guest-debug/run-test.py
index d865e46ecd..de6106a5e5 100755
--- a/tests/guest-debug/run-test.py
+++ b/tests/guest-debug/run-test.py
@@ -26,11 +26,12 @@ def get_args():
parser.add_argument("--qargs", help="Qemu arguments for test")
parser.add_argument("--binary", help="Binary to debug",
required=True)
- parser.add_argument("--test", help="GDB test script",
- required=True)
+ parser.add_argument("--test", help="GDB test script")
parser.add_argument("--gdb", help="The gdb binary to use",
default=None)
+ parser.add_argument("--gdb-args", help="Additional gdb arguments")
parser.add_argument("--output", help="A file to redirect output to")
+ parser.add_argument("--stderr", help="A file to redirect stderr to")
return parser.parse_args()
@@ -58,6 +59,10 @@ def log(output, msg):
output = open(args.output, "w")
else:
output = None
+ if args.stderr:
+ stderr = open(args.stderr, "w")
+ else:
+ stderr = None
socket_dir = TemporaryDirectory("qemu-gdbstub")
socket_name = os.path.join(socket_dir.name, "gdbstub.socket")
@@ -77,6 +82,8 @@ def log(output, msg):
# Now launch gdb with our test and collect the result
gdb_cmd = "%s %s" % (args.gdb, args.binary)
+ if args.gdb_args:
+ gdb_cmd += " %s" % (args.gdb_args)
# run quietly and ignore .gdbinit
gdb_cmd += " -q -n -batch"
# disable prompts in case of crash
@@ -84,13 +91,14 @@ def log(output, msg):
# connect to remote
gdb_cmd += " -ex 'target remote %s'" % (socket_name)
# finally the test script itself
- gdb_cmd += " -x %s" % (args.test)
+ if args.test:
+ gdb_cmd += " -x %s" % (args.test)
sleep(1)
log(output, "GDB CMD: %s" % (gdb_cmd))
- result = subprocess.call(gdb_cmd, shell=True, stdout=output)
+ result = subprocess.call(gdb_cmd, shell=True, stdout=output, stderr=stderr)
# A result of greater than 128 indicates a fatal signal (likely a
# crash due to gdb internal failure). That's a problem for GDB and
diff --git a/tests/tcg/multiarch/system/Makefile.softmmu-target b/tests/tcg/multiarch/system/Makefile.softmmu-target
index 625ed792c6..1bb6d89097 100644
--- a/tests/tcg/multiarch/system/Makefile.softmmu-target
+++ b/tests/tcg/multiarch/system/Makefile.softmmu-target
@@ -27,9 +27,23 @@ run-gdbstub-memory: memory
--bin $< --test $(MULTIARCH_SRC)/gdbstub/memory.py, \
"softmmu gdbstub support")
+run-gdbstub-untimely-packet: hello
+ $(call run-test, $@, $(GDB_SCRIPT) \
+ --gdb $(HAVE_GDB_BIN) \
+ --gdb-args "-ex 'set debug remote 1'" \
+ --output untimely-packet.gdb.out \
+ --stderr untimely-packet.gdb.err \
+ --qemu $(QEMU) \
+ --bin $< --qargs \
+ "-monitor none -display none -chardev file$(COMMA)path=untimely-packet.out$(COMMA)id=output $(QEMU_OPTS)", \
+ "softmmu gdbstub untimely packets")
+ $(call quiet-command, \
+ (! grep -Fq 'Packet instead of Ack, ignoring it' untimely-packet.gdb.err), \
+ "GREP", "file untimely-packet.gdb.err")
+
else
run-gdbstub-%:
$(call skip-test, "gdbstub test $*", "need working gdb")
endif
-MULTIARCH_RUNS += run-gdbstub-memory
+MULTIARCH_RUNS += run-gdbstub-memory run-gdbstub-untimely-packet
--
2.37.2
^ permalink raw reply related [flat|nested] 4+ messages in thread
end of thread, other threads:[~2022-09-20 15:29 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2022-09-20 12:47 [PATCH v3 0/3] gdbstub: avoid untimely stop-reply msgs Matheus Tavares Bernardino
2022-09-20 12:47 ` [PATCH v3 1/3] configure: make sure tcg tests can see HAVE_GDB_BIN Matheus Tavares Bernardino
2022-09-20 12:47 ` [PATCH v3 2/3] gdbstub: only send stop-reply packets when allowed to Matheus Tavares Bernardino
2022-09-20 12:47 ` [PATCH v3 3/3] gdbstub: add test for untimely stop-reply packets Matheus Tavares Bernardino
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).