From d401b1fbadff4a69059e6a2132ad500f34cf2c65 Mon Sep 17 00:00:00 2001 From: Quentin Forcioli Date: Tue, 16 Aug 2022 17:43:31 +0200 Subject: [PATCH] base,sim: Adding monitor function to GDB The remote protocol provides a monitor query. This query allows to provide a implementation defined behavior in the stub. I proposed to use this command as a way to quit simulation with a message provided by the GDB client. Thus calling "monitor my_message" in the client will exit the simulation with the exit message "GDB_MONITOR:my_message". This is implemented through a derived class based on GlobalSimLoopExitEvent and a small addition to the based class that adds a clean method that will be called when returning siumation after the Event. Change-Id: Ib5fda569edcf6733cbcc6240ef6d2ec4dc6502ec Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/63538 Maintainer: Bobby Bruce Reviewed-by: Bobby Bruce Tested-by: kokoro --- src/base/remote_gdb.cc | 46 +++++++++++++++++++++++++++++++++++++----- src/base/remote_gdb.hh | 1 + src/sim/eventq.hh | 1 + src/sim/sim_events.hh | 7 +++++-- src/sim/simulate.cc | 5 ++++- 5 files changed, 52 insertions(+), 8 deletions(-) diff --git a/src/base/remote_gdb.cc b/src/base/remote_gdb.cc index 47fae75cbb..43f53d1247 100644 --- a/src/base/remote_gdb.cc +++ b/src/base/remote_gdb.cc @@ -157,6 +157,7 @@ #include "mem/translating_port_proxy.hh" #include "sim/full_system.hh" #include "sim/process.hh" +#include "sim/sim_events.hh" #include "sim/system.hh" namespace gem5 @@ -241,7 +242,7 @@ hex2c(char c0,char c1) //this function will be used in a future patch //convert a encoded string to a string -[[maybe_unused]] std::string +std::string hexS2string(std::string hex_in) { std::string out=""; @@ -554,7 +555,6 @@ BaseRemoteGDB::trap(ContextID id, GDBSignal sig,const std::string& stopReason) return; if (tc->contextId() != id) { - //prevent thread switch when single stepping if (singleStepEvent.scheduled()){ return; @@ -564,11 +564,14 @@ BaseRemoteGDB::trap(ContextID id, GDBSignal sig,const std::string& stopReason) return; } + DPRINTF(GDBMisc, "trap: PC=%s\n", tc->pcState()); clearSingleStep(); - - if (threadSwitching) { + if (stopReason=="monitor_return"){ + //should wnot send any Tpacket here + send("OK"); + }else if (threadSwitching) { threadSwitching = false; // Tell GDB the thread switch has completed. send("OK"); @@ -1326,6 +1329,7 @@ splitAt(std::string str, const char * const delim) std::map BaseRemoteGDB::queryMap = { { "C", { &BaseRemoteGDB::queryC } }, + { "Rcmd", { &BaseRemoteGDB::queryRcmd} }, { "Attached", { &BaseRemoteGDB::queryAttached} }, { "Supported", { &BaseRemoteGDB::querySupported, ";" } }, { "Xfer", { &BaseRemoteGDB::queryXfer } }, @@ -1416,6 +1420,38 @@ BaseRemoteGDB::queryAttached(QuerySetCommand::Context &ctx) return true; } +class MonitorCallEvent : public GlobalSimLoopExitEvent +{ + BaseRemoteGDB& gdb; + ContextID id; + public: + MonitorCallEvent(BaseRemoteGDB& gdb,ContextID id,const std::string &_cause, + int code): + GlobalSimLoopExitEvent(_cause,code), gdb(gdb),id(id) + {}; + void process() override{ + GlobalSimLoopExitEvent::process(); + } + void clean() override{ + //trapping now + //this is the only point in time when we can call trap + //before any breakpoint triggers + gdb.trap(id,GDBSignal::ZERO,"monitor_return"); + delete this; + } + ~MonitorCallEvent(){ + DPRINTF(Event,"MonitorCallEvent destructed\n");; + } +}; + +bool +BaseRemoteGDB::queryRcmd(QuerySetCommand::Context &ctx){ + std::string message=hexS2string(ctx.args[0]); + DPRINTF(GDBMisc, "Rcmd Query: %s => %s\n", ctx.args[0],message); + //Tick when = curTick(); + new MonitorCallEvent(*this,tc->contextId(),"GDB_MONITOR:"+ message, 0); + return false; +} bool BaseRemoteGDB::queryFThreadInfo(QuerySetCommand::Context &ctx) @@ -1444,7 +1480,7 @@ BaseRemoteGDB::cmdQueryVar(GdbCommand::Context &ctx) { // The query command goes until the first ':', or the end of the string. std::string s(ctx.data, ctx.len); - auto query_split = splitAt({ ctx.data, (size_t)ctx.len }, ":"); + auto query_split = splitAt({ ctx.data, (size_t)ctx.len }, ":,"); const auto &query_str = query_split.first; // Look up the query command, and report if it isn't found. diff --git a/src/base/remote_gdb.hh b/src/base/remote_gdb.hh index c23b4ac95e..1c5cd9c7af 100644 --- a/src/base/remote_gdb.hh +++ b/src/base/remote_gdb.hh @@ -433,6 +433,7 @@ class BaseRemoteGDB bool querySupported(QuerySetCommand::Context &ctx); bool queryXfer(QuerySetCommand::Context &ctx); bool querySymbol(QuerySetCommand::Context &ctx); + bool queryRcmd(QuerySetCommand::Context &ctx); bool queryAttached(QuerySetCommand::Context &ctx); size_t threadInfoIdx = 0; diff --git a/src/sim/eventq.hh b/src/sim/eventq.hh index a7226ffead..cd5d285f93 100644 --- a/src/sim/eventq.hh +++ b/src/sim/eventq.hh @@ -46,6 +46,7 @@ #include "base/debug.hh" #include "base/flags.hh" +#include "base/trace.hh" #include "base/types.hh" #include "base/uncontended_mutex.hh" #include "debug/Event.hh" diff --git a/src/sim/sim_events.hh b/src/sim/sim_events.hh index 06a8e6548d..a1ffc7b34a 100644 --- a/src/sim/sim_events.hh +++ b/src/sim/sim_events.hh @@ -68,8 +68,11 @@ class GlobalSimLoopExitEvent : public GlobalEvent const std::string getCause() const { return cause; } int getCode() const { return code; } - void process(); // process event - + virtual void process();// process event + virtual void clean(){};//cleaning event + ~GlobalSimLoopExitEvent (){ + DPRINTF(Event,"GlobalSimLoopExitEvent destructed\n"); + }; virtual const char *description() const; }; diff --git a/src/sim/simulate.cc b/src/sim/simulate.cc index c5d07942ef..0c30f10570 100644 --- a/src/sim/simulate.cc +++ b/src/sim/simulate.cc @@ -184,9 +184,12 @@ struct DescheduleDeleter * terminate the loop. Exported to Python. * @return The SimLoopExitEvent that caused the loop to exit. */ +GlobalSimLoopExitEvent *global_exit_event= nullptr; GlobalSimLoopExitEvent * simulate(Tick num_cycles) { + if (global_exit_event)//cleaning last global exit event + global_exit_event->clean(); std::unique_ptr quantum_event; const Tick exit_tick = num_cycles < MaxTick - curTick() ? curTick() + num_cycles : MaxTick; @@ -224,7 +227,7 @@ simulate(Tick num_cycles) BaseGlobalEvent *global_event = local_event->globalEvent(); assert(global_event); - GlobalSimLoopExitEvent *global_exit_event = + global_exit_event = dynamic_cast(global_event); assert(global_exit_event);