diff --git a/RedPandaIDE/debugger/dapdebugger.cpp b/RedPandaIDE/debugger/dapdebugger.cpp index 95711491..374b8d8f 100644 --- a/RedPandaIDE/debugger/dapdebugger.cpp +++ b/RedPandaIDE/debugger/dapdebugger.cpp @@ -86,3 +86,8 @@ void DAPDebuggerClient::run() emit processFailed(mProcess->error()); } } + +DebuggerType DAPDebuggerClient::clientType() +{ + return DebuggerType::DAP; +} diff --git a/RedPandaIDE/debugger/dapdebugger.h b/RedPandaIDE/debugger/dapdebugger.h index 8e28d8fd..d87d0b6a 100644 --- a/RedPandaIDE/debugger/dapdebugger.h +++ b/RedPandaIDE/debugger/dapdebugger.h @@ -34,6 +34,7 @@ public: void postCommand(const QString &Command, const QString &Params, DebugCommandSource Source) override; void registerInferiorStoppedCommand(const QString &Command, const QString &Params) override; void stopDebug() override; + DebuggerType clientType() override; protected: void runNextCmd() override; diff --git a/RedPandaIDE/debugger/debugger.cpp b/RedPandaIDE/debugger/debugger.cpp index c43b5ddb..e7122f52 100644 --- a/RedPandaIDE/debugger/debugger.cpp +++ b/RedPandaIDE/debugger/debugger.cpp @@ -159,7 +159,7 @@ bool Debugger::start(int compilerSetIndex, const QString& inferior, const QStrin mTarget->waitStart(); } //delete when thread finished - mClient = new GDBMIDebuggerClient(this); + mClient = new GDBMIDebuggerClient(this, debuggerType()); mClient->addBinDirs(binDirs); mClient->addBinDir(pSettings->dirs().appDir()); mClient->setDebuggerPath(debuggerPath); @@ -270,10 +270,10 @@ void Debugger::updateRegisterValues(const QHash &values) void Debugger::refreshAll() { refreshWatchVars(); - if (mExecuting && mClient) + if (mClient) mClient->refreshStackVariables(); if (memoryModel()->startAddress()>0 - && mExecuting && mClient) + && mClient) mClient->readMemory( memoryModel()->startAddress(), pSettings->debugger().memoryViewRows(), @@ -291,16 +291,9 @@ std::shared_ptr Debugger::watchModel() const return mWatchModel; } -void Debugger::sendCommand(const QString &command, const QString ¶ms, DebugCommandSource source) -{ - if (mExecuting && mClient) { - mClient->postCommand(command,params,source); - } -} - bool Debugger::commandRunning() { - if (mExecuting && mClient) { + if (mClient) { return mClient->commandRunning(); } return false; @@ -308,7 +301,7 @@ bool Debugger::commandRunning() bool Debugger::inferiorRunning() { - if (mExecuting && mClient) { + if (mClient) { return mClient->inferiorRunning(); } return false; @@ -316,7 +309,7 @@ bool Debugger::inferiorRunning() void Debugger::interrupt() { - if (mExecuting && mClient) { + if (mClient) { mClient->interrupt(); } } @@ -441,7 +434,7 @@ PBreakpoint Debugger::breakpointAt(int line, const Editor *editor, int *index) void Debugger::setBreakPointCondition(int index, const QString &condition, bool forProject) { PBreakpoint breakpoint=mBreakpointModel->setBreakPointCondition(index,condition, forProject); - if (mExecuting && mClient) + if (mClient) mClient->setBreakpointCondition(breakpoint); } @@ -494,7 +487,7 @@ void Debugger::loadForProject(const QString &filename, const QString &projectFol void Debugger::addWatchpoint(const QString &expression) { QString s=expression.trimmed(); - if (mExecuting && mClient) { + if (mClient) { mClient->addWatchpoint(expression); } } @@ -536,31 +529,29 @@ void Debugger::modifyWatchVarExpression(const QString &oldExpr, const QString &n var->name.clear(); var->children.clear(); - if (mExecuting) { - sendWatchCommand(var); - } + sendWatchCommand(var); } } void Debugger::refreshWatchVars() { - if (mExecuting && mClient) { + if (mClient) { sendAllWatchVarsToDebugger(); if (mDebuggerType==DebuggerType::LLDB_MI) { for (PWatchVar var:mWatchModel->watchVars()) { if (!var->name.isEmpty()) - mClient->refreshWatchVar(var); + mClient->refreshWatch(var); } } else { - sendCommand("-var-update"," --all-values *"); + mClient->refreshWatch(); } } } void Debugger::fetchVarChildren(const QString &varName) { - if (mExecuting) { - sendCommand("-var-list-children",varName); + if (mClient) { + mClient->fetchWatchVarChildren(varName); } } @@ -648,6 +639,12 @@ PWatchVar Debugger::watchVarAt(const QModelIndex &index) return mWatchModel->findWatchVar(index); } +void Debugger::evalExpression(const QString &expression) +{ + if (mClient) + mClient->evalExpression(expression); +} + //void Debugger::notifyWatchVarUpdated(PWatchVar var) //{ // mWatchModel->notifyUpdated(var); @@ -664,36 +661,20 @@ std::shared_ptr Debugger::breakpointModel() void Debugger::sendWatchCommand(PWatchVar var) { - sendCommand("-var-create", var->expression); + if (mClient) + mClient->addWatch(var->expression); } void Debugger::sendRemoveWatchCommand(PWatchVar var) { - sendCommand("-var-delete",QString("%1").arg(var->name)); + if (mClient) + mClient->removeWatch(var); } void Debugger::sendBreakpointCommand(PBreakpoint breakpoint) { - if (breakpoint && mExecuting) { - // break "filename":linenum - QString condition; - if (!breakpoint->condition.isEmpty()) { - condition = " -c " + breakpoint->condition; - } - QString filename = breakpoint->filename; - filename.replace('\\','/'); - if (debuggerType()==DebuggerType::LLDB_MI) { - sendCommand("-break-insert", - QString("%1 \"%2:%3\"") - .arg(condition, filename) - .arg(breakpoint->line)); - } else { - sendCommand("-break-insert", - QString("%1 --source \"%2\" --line %3") - .arg(condition,filename) - .arg(breakpoint->line)); - } - } + if (mClient) + mClient->addBreakpoint(breakpoint); } void Debugger::sendClearBreakpointCommand(int index, bool forProject) @@ -703,14 +684,8 @@ void Debugger::sendClearBreakpointCommand(int index, bool forProject) void Debugger::sendClearBreakpointCommand(PBreakpoint breakpoint) { - // Debugger already running? Remove it from GDB - if (breakpoint && breakpoint->number>=0 && mExecuting) { - //clear "filename":linenum - QString filename = breakpoint->filename; - filename.replace('\\','/'); - sendCommand("-break-delete", - QString("%1").arg(breakpoint->number)); - } + if (mClient) + mClient->removeBreakpoint(breakpoint); } QJsonArray BreakpointModel::toJson(const QString& projectFolder) @@ -941,13 +916,15 @@ void Debugger::syncFinishedParsing() void Debugger::setMemoryData(qulonglong address, unsigned char data) { - sendCommand("-data-write-memory-bytes", QString("%1 \"%2\"").arg(address).arg(data,2,16,QChar('0'))); + if (mClient) + mClient->writeMemory(address, data); refreshAll(); } void Debugger::setWatchVarValue(const QString &name, const QString &value) { - sendCommand("-var-assign",QString("%1 %2").arg(name,value)); + if (mClient) + mClient->writeWatchVar(name, value); refreshAll(); } diff --git a/RedPandaIDE/debugger/debugger.h b/RedPandaIDE/debugger/debugger.h index 202f9162..88c9d44f 100644 --- a/RedPandaIDE/debugger/debugger.h +++ b/RedPandaIDE/debugger/debugger.h @@ -303,8 +303,6 @@ public: ~Debugger(); // Play/pause bool start(int compilerSetIndex, const QString& inferior, const QStringList& binDirs, const QString& sourceFile=QString()); - void sendCommand(const QString& command, const QString& params, - DebugCommandSource source = DebugCommandSource::Other); bool commandRunning(); bool inferiorRunning(); void interrupt(); @@ -345,6 +343,10 @@ public: PWatchVar findWatchVar(const QString& expression); PWatchVar watchVarAt(const QModelIndex& index); void refreshVars(); + + void evalExpression(const QString& expression); + + // void notifyWatchVarUpdated(PWatchVar var); std::shared_ptr backtraceModel(); @@ -493,13 +495,33 @@ public: Debugger* debugger() { return mDebugger; } + virtual DebuggerType clientType() = 0; + //requests virtual void interrupt() = 0; virtual void refreshStackVariables() = 0; + virtual void readMemory(qulonglong startAddress, int rows, int cols) = 0; - virtual void setBreakpointCondition(PBreakpoint breakpoint) = 0; + virtual void writeMemory(qulonglong address, unsigned char data) = 0; + + virtual void addBreakpoint(PBreakpoint breakpoint) = 0; + virtual void removeBreakpoint(PBreakpoint breakpoint) = 0; virtual void addWatchpoint(const QString& watchExp) = 0; - virtual void refreshWatchVar(PWatchVar var) = 0; + virtual void setBreakpointCondition(PBreakpoint breakpoint) = 0; + + virtual void addWatch(const QString& expression) = 0; + virtual void removeWatch(PWatchVar watchVar) = 0; + virtual void writeWatchVar(const QString& varName, const QString& value) = 0; + virtual void refreshWatch(PWatchVar var) = 0; + virtual void refreshWatch() = 0; + virtual void fetchWatchVarChildren(const QString& varName) = 0; + + virtual void evalExpression(const QString& expression) = 0; + + virtual void refreshFrame() = 0; + virtual void refreshRegisters() = 0; + virtual void disassembleCurrentFrame(bool blendMode) = 0; + signals: void parseStarted(); diff --git a/RedPandaIDE/debugger/gdbmidebugger.cpp b/RedPandaIDE/debugger/gdbmidebugger.cpp index bf23ef9c..b8f09d43 100644 --- a/RedPandaIDE/debugger/gdbmidebugger.cpp +++ b/RedPandaIDE/debugger/gdbmidebugger.cpp @@ -26,8 +26,12 @@ const QRegularExpression GDBMIDebuggerClient::REGdbSourceLine("^(\\d)+\\s+in\\s+(.+)$"); -GDBMIDebuggerClient::GDBMIDebuggerClient(Debugger *debugger, QObject *parent): - DebuggerClient(debugger, parent) +GDBMIDebuggerClient::GDBMIDebuggerClient( + Debugger *debugger, + DebuggerType clientType, + QObject *parent): + DebuggerClient{debugger, parent}, + mClientType{clientType} { mProcess = std::make_shared(); mAsyncUpdated = false; @@ -61,6 +65,11 @@ void GDBMIDebuggerClient::stopDebug() mStop = true; } +DebuggerType GDBMIDebuggerClient::clientType() +{ + return mClientType; +} + void GDBMIDebuggerClient::run() { mStop = false; @@ -867,12 +876,12 @@ const PDebugCommand &GDBMIDebuggerClient::currentCmd() const void GDBMIDebuggerClient::interrupt() { - postCommand("-exec-interrupt", "", DebugCommandSource::Other); + postCommand("-exec-interrupt", ""); } void GDBMIDebuggerClient::refreshStackVariables() { - postCommand("-stack-list-variables", "--all-values", DebugCommandSource::Other); + postCommand("-stack-list-variables", "--all-values"); } void GDBMIDebuggerClient::readMemory(qulonglong startAddress, int rows, int cols) @@ -880,9 +889,47 @@ void GDBMIDebuggerClient::readMemory(qulonglong startAddress, int rows, int cols postCommand("-data-read-memory",QString("%1 x 1 %2 %3 ") .arg(startAddress) .arg(rows) - .arg(cols), - DebugCommandSource::Other - ); + .arg(cols)); +} + +void GDBMIDebuggerClient::writeMemory(qulonglong address, unsigned char data) +{ + postCommand("-data-write-memory-bytes", QString("%1 \"%2\"").arg(address).arg(data,2,16,QChar('0'))); +} + +void GDBMIDebuggerClient::addBreakpoint(PBreakpoint breakpoint) +{ + if (breakpoint) { + // break "filename":linenum + QString condition; + if (!breakpoint->condition.isEmpty()) { + condition = " -c " + breakpoint->condition; + } + QString filename = breakpoint->filename; + filename.replace('\\','/'); + if (clientType()==DebuggerType::LLDB_MI) { + postCommand("-break-insert", + QString("%1 \"%2:%3\"") + .arg(condition, filename) + .arg(breakpoint->line)); + } else { + postCommand("-break-insert", + QString("%1 --source \"%2\" --line %3") + .arg(condition,filename) + .arg(breakpoint->line)); + } + } +} + +void GDBMIDebuggerClient::removeBreakpoint(PBreakpoint breakpoint) +{ + if (breakpoint && breakpoint->number>=0) { + //clear "filename":linenum + QString filename = breakpoint->filename; + filename.replace('\\','/'); + postCommand("-break-delete", + QString("%1").arg(breakpoint->number)); + } } void GDBMIDebuggerClient::setBreakpointCondition(PBreakpoint breakpoint) @@ -891,25 +938,72 @@ void GDBMIDebuggerClient::setBreakpointCondition(PBreakpoint breakpoint) QString condition = breakpoint->condition; if (condition.isEmpty()) { postCommand("-break-condition", - QString("%1").arg(breakpoint->number), DebugCommandSource::Other); + QString("%1").arg(breakpoint->number)); } else { postCommand("-break-condition", - QString("%1 %2").arg(breakpoint->number).arg(condition), DebugCommandSource::Other); + QString("%1 %2").arg(breakpoint->number).arg(condition)); } } +void GDBMIDebuggerClient::addWatch(const QString &expression) +{ + postCommand("-var-create", expression); +} + +void GDBMIDebuggerClient::removeWatch(PWatchVar watchVar) +{ + postCommand("-var-delete",QString("%1").arg(watchVar->name)); +} + +void GDBMIDebuggerClient::writeWatchVar(const QString &varName, const QString &value) +{ + postCommand("-var-assign",QString("%1 %2").arg(varName, value)); +} + void GDBMIDebuggerClient::addWatchpoint(const QString &watchExp) { if (!watchExp.isEmpty()) - postCommand("-break-watch", watchExp, DebugCommandSource::Other); + postCommand("-break-watch", watchExp); } -void GDBMIDebuggerClient::refreshWatchVar(PWatchVar var) +void GDBMIDebuggerClient::refreshWatch(PWatchVar var) { Q_ASSERT(var!=nullptr); postCommand("-var-update", - QString(" --all-values %1").arg(var->name), - DebugCommandSource::Other); + QString(" --all-values %1").arg(var->name)); +} + +void GDBMIDebuggerClient::refreshWatch() +{ + postCommand("-var-update"," --all-values *"); +} + +void GDBMIDebuggerClient::fetchWatchVarChildren(const QString& varName) +{ + postCommand("-var-list-children", varName); +} + +void GDBMIDebuggerClient::evalExpression(const QString &expression) +{ + postCommand("-data-evaluate-expression", expression); +} + +void GDBMIDebuggerClient::refreshFrame() +{ + postCommand("-stack-info-frame", ""); +} + +void GDBMIDebuggerClient::refreshRegisters() +{ + postCommand("-data-list-register-values", "N"); +} + +void GDBMIDebuggerClient::disassembleCurrentFrame(bool blendMode) +{ + if (blendMode) + postCommand("disas", "/s"); + else + postCommand("disas", ""); } void GDBMIDebuggerClient::runInferiorStoppedHook() diff --git a/RedPandaIDE/debugger/gdbmidebugger.h b/RedPandaIDE/debugger/gdbmidebugger.h index 6d8c1127..3a09504d 100644 --- a/RedPandaIDE/debugger/gdbmidebugger.h +++ b/RedPandaIDE/debugger/gdbmidebugger.h @@ -38,21 +38,39 @@ using PDebugCommand = std::shared_ptr; class GDBMIDebuggerClient: public DebuggerClient { Q_OBJECT public: - explicit GDBMIDebuggerClient(Debugger* debugger, QObject *parent = nullptr); + explicit GDBMIDebuggerClient(Debugger* debugger, DebuggerType clientType, QObject *parent = nullptr); // DebuggerClient interface public: - void postCommand(const QString &Command, const QString &Params, DebugCommandSource Source) override; + void postCommand(const QString &Command, const QString &Params, DebugCommandSource Source = DebugCommandSource::Other) override; void registerInferiorStoppedCommand(const QString &Command, const QString &Params) override; void stopDebug() override; + DebuggerType clientType() override; const PDebugCommand ¤tCmd() const; void interrupt() override; void refreshStackVariables() override; + void readMemory(qulonglong startAddress, int rows, int cols) override; - void setBreakpointCondition(PBreakpoint breakpoint) override; + void writeMemory(qulonglong address, unsigned char data) override; + + void addBreakpoint(PBreakpoint breakpoint) override; + void removeBreakpoint(PBreakpoint breakpoint) override; void addWatchpoint(const QString& watchExp) override; - void refreshWatchVar(PWatchVar var) override; + void setBreakpointCondition(PBreakpoint breakpoint) override; + + void addWatch(const QString& expression) override; + void removeWatch(PWatchVar watchVar) override; + void writeWatchVar(const QString& varName, const QString& value) override; + void refreshWatch(PWatchVar var) override; + void refreshWatch() override; + void fetchWatchVarChildren(const QString& varName) override; + + void evalExpression(const QString& expression) override; + + void refreshFrame(); + void refreshRegisters(); + void disassembleCurrentFrame(bool blendMode); // QThread interface protected: void run() override; @@ -100,6 +118,7 @@ private: PDebugCommand mCurrentCmd; QList mInferiorStoppedHookCommands; + DebuggerType mClientType; }; #endif // GDBMI_DEBUGGER_H diff --git a/RedPandaIDE/editor.cpp b/RedPandaIDE/editor.cpp index d34cd7dc..cbcdb269 100644 --- a/RedPandaIDE/editor.cpp +++ b/RedPandaIDE/editor.cpp @@ -4108,7 +4108,7 @@ void Editor::showDebugHint(const QString &s, int line) connect(pMainWindow->debugger(), &Debugger::evalValueReady, this, &Editor::onTipEvalValueReady); mCurrentDebugTipWord = s; - pMainWindow->debugger()->sendCommand("-data-evaluate-expression",s); + pMainWindow->debugger()->evalExpression(s); } QString Editor::getErrorHint(const PSyntaxIssue& issue) diff --git a/RedPandaIDE/mainwindow.cpp b/RedPandaIDE/mainwindow.cpp index 8becdd0b..187d6d11 100644 --- a/RedPandaIDE/mainwindow.cpp +++ b/RedPandaIDE/mainwindow.cpp @@ -6501,7 +6501,7 @@ void MainWindow::onDebugEvaluateInput() if (!s.isEmpty()) { connect(mDebugger.get(), &Debugger::evalValueReady, this, &MainWindow::onEvalValueReady); - mDebugger->sendCommand("-data-evaluate-expression",s); + mDebugger->evalExpression(s); pMainWindow->debugger()->refreshAll(); } }