gdbstub: Switch to the thread receiving a signal

Respond with Txxthread:yyyy; instead of a plain Sxx to indicate which
thread received the signal. Otherwise, the debugger will associate it
with the main one. Also automatically select this thread, as that is
what gdb expects.

Signed-off-by: Pavel Labath <pavel@labath.sk>
Message-Id: <20211019174953.36560-1-pavel@labath.sk>
Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Message-Id: <20211026102234.3961636-29-alex.bennee@linaro.org>
This commit is contained in:
Pavel Labath 2021-10-26 11:22:34 +01:00 committed by Alex Bennée
parent 8ef3fdf952
commit 4a82be77de
3 changed files with 75 additions and 3 deletions

View File

@ -3138,8 +3138,12 @@ gdb_handlesig(CPUState *cpu, int sig)
tb_flush(cpu);
if (sig != 0) {
snprintf(buf, sizeof(buf), "S%02x", target_signal_to_gdb(sig));
put_packet(buf);
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();
}
/* put_packet() might have detected that the peer terminated the
connection. */

View File

@ -68,11 +68,19 @@ run-gdbstub-qxfer-auxv-read: sha1
--bin $< --test $(MULTIARCH_SRC)/gdbstub/test-qxfer-auxv-read.py, \
"basic gdbstub qXfer:auxv:read support")
run-gdbstub-thread-breakpoint: testthread
$(call run-test, $@, $(GDB_SCRIPT) \
--gdb $(HAVE_GDB_BIN) \
--qemu $(QEMU) --qargs "$(QEMU_OPTS)" \
--bin $< --test $(MULTIARCH_SRC)/gdbstub/test-thread-breakpoint.py, \
"hitting a breakpoint on non-main thread")
else
run-gdbstub-%:
$(call skip-test, "gdbstub test $*", "need working gdb")
endif
EXTRA_RUNS += run-gdbstub-sha1 run-gdbstub-qxfer-auxv-read
EXTRA_RUNS += run-gdbstub-sha1 run-gdbstub-qxfer-auxv-read \
run-gdbstub-thread-breakpoint
# ARM Compatible Semi Hosting Tests
#

View File

@ -0,0 +1,60 @@
from __future__ import print_function
#
# Test auxiliary vector is loaded via gdbstub
#
# This is launched via tests/guest-debug/run-test.py
#
import gdb
import sys
failcount = 0
def report(cond, msg):
"Report success/fail of test"
if cond:
print ("PASS: %s" % (msg))
else:
print ("FAIL: %s" % (msg))
global failcount
failcount += 1
def run_test():
"Run through the tests one by one"
sym, ok = gdb.lookup_symbol("thread1_func")
gdb.execute("b thread1_func")
gdb.execute("c")
frame = gdb.selected_frame()
report(str(frame.function()) == "thread1_func", "break @ %s"%frame)
#
# This runs as the script it sourced (via -x, via run-test.py)
#
try:
inferior = gdb.selected_inferior()
arch = inferior.architecture()
print("ATTACHED: %s" % arch.name())
except (gdb.error, AttributeError):
print("SKIPPING (not connected)", file=sys.stderr)
exit(0)
if gdb.parse_and_eval('$pc') == 0:
print("SKIP: PC not set")
exit(0)
try:
# These are not very useful in scripts
gdb.execute("set pagination off")
gdb.execute("set confirm off")
# Run the actual tests
run_test()
except (gdb.error):
print ("GDB Exception: %s" % (sys.exc_info()[0]))
failcount += 1
pass
print("All tests complete: %d failures" % failcount)
exit(failcount)