diff --git a/src/frontends/qriscv/debug_session.cc b/src/frontends/qriscv/debug_session.cc index adb6a44..4b3129f 100644 --- a/src/frontends/qriscv/debug_session.cc +++ b/src/frontends/qriscv/debug_session.cc @@ -11,6 +11,7 @@ #include #include #include +#include #include "qriscv/application.h" #include "uriscv/error.h" @@ -52,6 +53,19 @@ void DebugSession::halt() { setStatus(MS_HALTED); } +void DebugSession::killServer(){ + if(isGdbEnabled()){ + int w = 0; + w = gdb->killServer(); + while(w != 1){ + //wait till the server correctly shutdown + } + printf("gdb server terminated\n"); + + gdb->~GDBServer(); + } +} + void DebugSession::setSpeed(int value) { value = qBound(0, value, kMaxSpeed); if (speed != value) { @@ -70,6 +84,10 @@ void DebugSession::setStopMask(unsigned int value) { machine->setStopMask(stopMask); } +void DebugSession::setGdbStatus(bool newStatus){ + GdbStatus = newStatus; +} + void DebugSession::createActions() { startMachineAction = new QAction("Power On", this); startMachineAction->setShortcut(QKeySequence("F5")); @@ -174,6 +192,12 @@ void DebugSession::initializeMachine() { try { machine.reset(new Machine(config, &breakpoints, &suspects, &tracepoints)); + if (isGdbEnabled()) { + gts = std::thread([&]() { + gdb = new GDBServer(machine.get()); + gdb->StartServer(); }); + gts.detach(); + } } catch (const FileError &e) { QMessageBox::critical( Appl()->getApplWindow(), @@ -266,6 +290,7 @@ void DebugSession::startMachine() { void DebugSession::onHaltMachine() { assert(status != MS_HALTED); + killServer(); halt(); } @@ -282,6 +307,9 @@ void DebugSession::onResetMachine() { stop(); machine.reset(); + + killServer(); + initializeMachine(); if (machine) { Q_EMIT MachineReset(); @@ -443,4 +471,4 @@ void DebugSession::relocateStoppoints(const SymbolTable *newTable, } set = rset; -} +} \ No newline at end of file diff --git a/src/frontends/qriscv/monitor_window.cc b/src/frontends/qriscv/monitor_window.cc index 5076667..2bd2851 100644 --- a/src/frontends/qriscv/monitor_window.cc +++ b/src/frontends/qriscv/monitor_window.cc @@ -11,6 +11,8 @@ #include +#include "gdb/gdb.h" + #include "uriscv/device.h" #include "uriscv/error.h" #include "uriscv/machine.h" @@ -173,6 +175,13 @@ void MonitorWindow::createActions() { removeTraceAction = new QAction("Remove Traced Region", this); removeTraceAction->setEnabled(false); + //GDB server + enableGDBserver = new QAction("Enable GDB Server", this); + enableGDBserver->setCheckable(true); + enableGDBserver->setChecked(debugSession->isGdbEnabled()); + connect(enableGDBserver, SIGNAL(triggered()),this, SLOT(onEnableGDBserver())); + enableGDBserver->setEnabled(true); + speedActionGroup = new QActionGroup(this); for (int i = 0; i < DebugSession::kNumSpeedLevels; i++) { simSpeedActions[i] = new QAction(simSpeedMnemonics[i], speedActionGroup); @@ -279,6 +288,10 @@ void MonitorWindow::createMenu() { stopMaskSubMenu->addAction(it->second); } + debugMenu->addSeparator(); + QMenu *gdbMenu = debugMenu->addMenu("GDB Server"); + gdbMenu->addAction(enableGDBserver); //power one the server + QMenu *settingsMenu = menuBar()->addMenu("Se&ttings"); QMenu *speedLevelsSubMenu = settingsMenu->addMenu("Simulation Speed"); for (int i = 0; i < DebugSession::kNumSpeedLevels; i++) @@ -797,6 +810,10 @@ void MonitorWindow::onAddTracepoint() { "it overlaps with an already inserted range"); } +void MonitorWindow::onEnableGDBserver(){ + dbgSession->setGdbStatus(!dbgSession->isGdbEnabled()); +} + StatusDisplay::StatusDisplay(QWidget *parent) : QWidget(parent) { QHBoxLayout *layout = new QHBoxLayout(this); layout->setContentsMargins(0, 0, 0, 0); diff --git a/src/gdb/gdb.cc b/src/gdb/gdb.cc index 829ce36..b6a63af 100644 --- a/src/gdb/gdb.cc +++ b/src/gdb/gdb.cc @@ -47,11 +47,31 @@ pthread_mutex_t stopped_mutex = PTHREAD_MUTEX_INITIALIZER; pthread_mutex_t bp_mutex = PTHREAD_MUTEX_INITIALIZER; GDBServer::GDBServer(Machine *mac) { - this->killed = false; this->stopped = false; this->mac = mac; } +GDBServer::~GDBServer() { + this->mac = NULL; +} + +GDBServer *gdb = NULL; +bool *killed_ptr = NULL; + +int GDBServer::killServer() { + pthread_mutex_lock(&stopped_mutex); + stopped = true; // stop the machine + pthread_mutex_unlock(&stopped_mutex); + + pthread_mutex_lock(&continue_mutex); + killed = true; + pthread_cond_signal(&continue_cond); // wake up the waiting thread + pthread_mutex_unlock(&continue_mutex); + + return 1; +} + + inline std::string GDBServer::getMsg(const std::string &msg) { static std::regex reg(R"(.*\$(.*)#.*)"); std::smatch matches; @@ -238,6 +258,10 @@ std::string GDBServer::ReadData(const std::string &msg) { return OKReply; } else if (body.c_str()[0] == 'c') { + pthread_mutex_lock(&stopped_mutex); + stopped = false; + pthread_mutex_unlock(&stopped_mutex); + pthread_mutex_lock(&continue_mutex); pthread_cond_signal(&continue_cond); pthread_mutex_unlock(&continue_mutex); @@ -252,6 +276,9 @@ std::string GDBServer::ReadData(const std::string &msg) { uint addr = parseBreakpoint(body); addBreakpoint(addr); return OKReply; + } else if (body.c_str()[0] == 's'){ + stepIn(); + return OKReply; } else if (strcmp(body.c_str(), vContMsg) == 0) { /* Not supported */ return emptyReply; @@ -262,14 +289,14 @@ std::string GDBServer::ReadData(const std::string &msg) { void *MachineStep(void *vargp) { - GDBServer *gdb = (GDBServer *)vargp; - - while (true) { - + while (!(*killed_ptr)) { pthread_mutex_lock(&continue_mutex); - pthread_cond_wait(&continue_cond, &continue_mutex); + pthread_cond_wait(&continue_cond, &continue_mutex); pthread_mutex_unlock(&continue_mutex); + if (*killed_ptr) { + break; // Exit the loop if killed + } bool s = false; do { gdb->Step(); @@ -277,7 +304,7 @@ void *MachineStep(void *vargp) { pthread_mutex_lock(&stopped_mutex); s = gdb->IsStopped(); pthread_mutex_unlock(&stopped_mutex); - } while (!gdb->CheckBreakpoint() && !s); + } while (!(*killed_ptr) && !gdb->CheckBreakpoint() && !s); if (!s) { pthread_mutex_lock(&stopped_mutex); @@ -297,6 +324,14 @@ void GDBServer::sendMsg(const int &socket, const std::string &msg) { send(socket, reply.c_str(), (reply).size(), 0); } +void GDBServer::stepIn(){ + gdb->Step(); + + pthread_mutex_lock(&stopped_mutex); + gdb->Stop(); + pthread_mutex_unlock(&stopped_mutex); +} + void GDBServer::StartServer() { DEBUGMSG("[GDB] Starting GDB Server\n"); @@ -305,6 +340,7 @@ void GDBServer::StartServer() { int opt = 1; int addrlen = sizeof(address); char buffer[1024] = {0}; + this->killed = false; // Creating socket file descriptor if ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { @@ -332,7 +368,9 @@ void GDBServer::StartServer() { exit(EXIT_FAILURE); } - for (;;) { + gdb = (GDBServer *)(this); + + killed_ptr = &killed; pthread_t tid; @@ -381,10 +419,9 @@ void GDBServer::StartServer() { pthread_kill(tid, SIGTERM); - // closing the connected socket + // clong the connected socket close(new_socket); - } // closing the listening socket shutdown(server_fd, SHUT_RDWR); -} +} \ No newline at end of file diff --git a/src/include/gdb/gdb.h b/src/include/gdb/gdb.h index 2dc7902..0ae53d8 100644 --- a/src/include/gdb/gdb.h +++ b/src/include/gdb/gdb.h @@ -2,6 +2,9 @@ // // SPDX-License-Identifier: GPL-3.0-or-later +#ifndef GDB_SERVER_H +#define GDB_SERVER_H + #include "uriscv/machine.h" #include #include @@ -16,6 +19,7 @@ class GDBServer { public: GDBServer(Machine *mac); + ~GDBServer(); void StartServer(); static std::string GetChecksum(const std::string &msg) { @@ -43,8 +47,11 @@ class GDBServer { inline void Stop() { stopped = true; }; bool IsStopped() const { return stopped; }; + int killServer() ; + bool isKilled() { return killed; }; + private: - bool killed, stopped; + bool killed = true, stopped; Machine *mac; std::vector breakpoints; @@ -61,9 +68,13 @@ class GDBServer { inline void removeBreakpoint(const uint &addr); void sendMsg(const int &socket, const std::string &msg); + + void stepIn(); }; typedef struct thread_arg_struct { GDBServer *gdb; int socket; } thread_arg_t; + +#endif // GDB_SERVER_H diff --git a/src/include/qriscv/debug_session.h b/src/include/qriscv/debug_session.h index 7bcfdbd..03ebae0 100644 --- a/src/include/qriscv/debug_session.h +++ b/src/include/qriscv/debug_session.h @@ -6,6 +6,7 @@ #define QRISCV_DEBUG_SESSION_H #include +#include #include "base/lang.h" #include "qriscv/cpu_status_map.h" @@ -13,6 +14,7 @@ #include "uriscv/machine.h" #include "uriscv/stoppoint.h" #include "uriscv/symbol_table.h" +#include "gdb/gdb.h" enum MachineStatus { MS_HALTED, MS_RUNNING, MS_STOPPED }; @@ -40,6 +42,7 @@ class DebugSession : public QObject { bool isStarted() const { return status != MS_HALTED; } void halt(); + void killServer(); unsigned int getStopMask() const { return stopMask; } int getSpeed() const { return speed; } @@ -66,6 +69,10 @@ class DebugSession : public QObject { QAction *debugStopAction; QAction *debugToggleAction; + //GDB stub + void setGdbStatus(bool value); + bool isGdbEnabled() { return GdbStatus; } + public Q_SLOTS: void setStopMask(unsigned int value); void setSpeed(int value); @@ -90,6 +97,8 @@ public Q_SLOTS: void initializeMachine(); + void initializeThreadServer(MachineConfig*); + void step(unsigned int steps); void runStepIteration(); void runContIteration(); @@ -126,6 +135,10 @@ public Q_SLOTS: uint32_t idleSteps; + bool GdbStatus = false; + std::thread gts; + GDBServer *gdb; + private Q_SLOTS: void onMachineConfigChanged(); @@ -143,4 +156,4 @@ private Q_SLOTS: void skip(); }; -#endif // QRISCV_DEBUG_SESSION_H +#endif // QRISCV_DEBUG_SESSION_H \ No newline at end of file diff --git a/src/include/qriscv/monitor_window.h b/src/include/qriscv/monitor_window.h index 5955bc7..de11e72 100644 --- a/src/include/qriscv/monitor_window.h +++ b/src/include/qriscv/monitor_window.h @@ -95,6 +95,8 @@ class MonitorWindow : public QMainWindow { QAction *addTraceAction; QAction *removeTraceAction; + QAction *enableGDBserver; + QActionGroup *speedActionGroup; QAction *simSpeedActions[DebugSession::kNumSpeedLevels]; static const char *const simSpeedMnemonics[DebugSession::kNumSpeedLevels]; @@ -159,6 +161,8 @@ private Q_SLOTS: void onAddSuspect(); void onRemoveSuspect(); void onAddTracepoint(); + + void onEnableGDBserver(); }; #endif // QRISCV_MONITOR_WINDOW_H