Skip to content

Commit

Permalink
Merge branch 'gdb-vcont-fixes' into 'master'
Browse files Browse the repository at this point in the history
gdb-mc: Only execute leftmost action with matching thread id in vCont

See merge request riscv/riscv-vp!33
  • Loading branch information
Cirromulus committed Feb 25, 2021
2 parents 071c1ea + a4bfecf commit a2e6d78
Showing 4 changed files with 28 additions and 6 deletions.
6 changes: 4 additions & 2 deletions vp/src/core/common/gdb-mc/gdb_server.cpp
Original file line number Diff line number Diff line change
@@ -137,9 +137,11 @@ void GDBServer::exec_thread(thread_func fn, char op) {
fn(thread);
}

std::vector<debug_target_if *> GDBServer::run_threads(int id, bool single) {
std::vector<debug_target_if *> GDBServer::run_threads(std::vector<debug_target_if *> hartsrun, bool single) {
if (hartsrun.empty()) {
return hartsrun;
}
this->single_run = single;
std::vector<debug_target_if *> hartsrun = get_threads(id);

/* invoke all selected harts */
sc_core::sc_event_or_list allharts;
2 changes: 1 addition & 1 deletion vp/src/core/common/gdb-mc/gdb_server.h
Original file line number Diff line number Diff line change
@@ -87,7 +87,7 @@ SC_MODULE(GDBServer) {
std::vector<debug_target_if *> get_threads(int);
uint64_t translate_addr(debug_target_if *, uint64_t, MemoryAccessType type);
void exec_thread(thread_func, char = 'g');
std::vector<debug_target_if *> run_threads(int, bool = false);
std::vector<debug_target_if *> run_threads(std::vector<debug_target_if *>, bool = false);
void writeall(int, char *, size_t);
void send_packet(int, const char *, gdb_kind_t = GDB_KIND_PACKET);
void retransmit(int);
24 changes: 22 additions & 2 deletions vp/src/core/common/gdb-mc/handler.cpp
Original file line number Diff line number Diff line change
@@ -208,6 +208,7 @@ void GDBServer::vCont(int conn, gdb_command_t *cmd) {
gdb_vcont_t *vcont;
int stopped_thread = -1;
const char *stop_reason = NULL;
std::map<debug_target_if *, bool> matched;

/* This handler attempts to implement the all-stop mode.
* See: https://sourceware.org/gdb/onlinedocs/gdb/All_002dStop-Mode.html */
@@ -217,12 +218,21 @@ void GDBServer::vCont(int conn, gdb_command_t *cmd) {
bool single = false;
if (vcont->action == 's')
single = true;
else if (vcont->action == 'S')
else if (vcont->action != 'c')
throw std::invalid_argument("Unimplemented vCont action"); /* TODO */

std::vector<debug_target_if *> selected_harts;
try {
selected_harts = run_threads(vcont->thread.tid, single);
auto run = get_threads(vcont->thread.tid);
for (auto i = run.begin(); i != run.end();) {
debug_target_if *hart = *i;
if (matched.count(hart))
i = run.erase(i); /* already matched */
else
i++;
}

selected_harts = run_threads(run, single);
} catch (const std::out_of_range&) {
send_packet(conn, "E01");
return;
@@ -246,6 +256,16 @@ void GDBServer::vCont(int conn, gdb_command_t *cmd) {
continue;
}
}

/* The vCont specification mandates that only the leftmost action with
* a matching thread-id is applied. Unfortunately, the specification
* is a bit unclear in regards to handling two actions with no thread
* id (i.e. GDB_THREAD_ALL). */
if (vcont->thread.tid > 0) {
auto threads = get_threads(vcont->thread.tid);
assert(threads.size() == 1);
matched[threads.front()] = true;
}
}

assert(stop_reason && stopped_thread >= 1);
2 changes: 1 addition & 1 deletion vp/src/core/common/gdb-mc/libgdb/parser2.c
Original file line number Diff line number Diff line change
@@ -223,7 +223,7 @@ gdbf_vcont(int n, mpc_val_t **xs)
vcont->next = (gdb_vcont_t *)xs[i];
vcont->next = NULL;

return vcont;
return (gdb_vcont_t *)xs[0];
}

gdbf_fold(vcont, GDB_ARG_VCONT, GDBF_ARG_VCONT)

0 comments on commit a2e6d78

Please sign in to comment.