diff --git a/RedPandaIDE/debugger.cpp b/RedPandaIDE/debugger.cpp index a3fb8282..761358d5 100644 --- a/RedPandaIDE/debugger.cpp +++ b/RedPandaIDE/debugger.cpp @@ -12,6 +12,9 @@ #include #include #include +#include +#include +#include Debugger::Debugger(QObject *parent) : QObject(parent) { @@ -63,6 +66,7 @@ bool Debugger::start() connect(this, &Debugger::localsReady,pMainWindow,&MainWindow::onLocalsReady); connect(mReader, &DebugReader::cmdStarted,pMainWindow, &MainWindow::disableDebugActions); connect(mReader, &DebugReader::cmdFinished,pMainWindow, &MainWindow::enableDebugActions); + connect(mReader, &DebugReader::breakpointInfoGetted, mBreakpointModel, &BreakpointModel::updateBreakpointNumber); @@ -455,23 +459,17 @@ void Debugger::syncFinishedParsing() } // An evaluation variable has been processed. Forward the results - if (mReader->doevalready) { + if (mReader->evalReady()) { //pMainWindow->updateDebugEval(mReader->mEvalValue); - emit evalValueReady(mReader->mEvalValue); - mReader->mEvalValue=""; - mReader->doevalready = false; + emit evalValueReady(mReader->evalValue()); } - if (mReader->doupdatememoryview) { - emit memoryExamineReady(mReader->mMemoryValue); - mReader->mMemoryValue.clear(); - mReader->doupdatememoryview=false; + if (mReader->updateMemory()) { + emit memoryExamineReady(mReader->memoryValue()); } - if (mReader->doupdatelocal) { - emit localsReady(mReader->mLocalsValue); - mReader->mLocalsValue.clear(); - mReader->doupdatelocal=false; + if (mReader->updateLocals()) { + emit localsReady(mReader->localsValue()); } // show command output @@ -521,16 +519,17 @@ void Debugger::syncFinishedParsing() } } - if (mReader->doupdateexecution) { - if (mReader->mCurrentCmd && mReader->mCurrentCmd->source == DebugCommandSource::Console) { - pMainWindow->setActiveBreakpoint(mReader->mBreakPointFile, mReader->mBreakPointLine,false); + if (mReader->updateExecution()) { + if (mReader->currentCmd() && mReader->currentCmd()->source == DebugCommandSource::Console) { + pMainWindow->setActiveBreakpoint(mReader->breakPointFile(), mReader->breakPointLine(),false); } else { - pMainWindow->setActiveBreakpoint(mReader->mBreakPointFile, mReader->mBreakPointLine); + pMainWindow->setActiveBreakpoint(mReader->breakPointFile(), mReader->breakPointLine()); } refreshWatchVars(); // update variable information } - if (mReader->doreceivedsignal) { + if (mReader->signalReceived()) { + //SignalDialog := CreateMessageDialog(fSignal, mtError, [mbOk]); //SignalCheck := TCheckBox.Create(SignalDialog); @@ -563,7 +562,7 @@ void Debugger::syncFinishedParsing() // CPU form updates itself when spawned, don't update twice! - if ((mReader->doupdatecpuwindow && !spawnedcpuform) && (pMainWindow->cpuDialog()!=nullptr)) { + if ((mReader->updateCPUInfo() && !spawnedcpuform) && (pMainWindow->cpuDialog()!=nullptr)) { pMainWindow->cpuDialog()->updateInfo(); } } @@ -903,86 +902,6 @@ void DebugReader::handleExit() doprocessexited=true; } -void DebugReader::handleFrames() -{ - QString s = getNextLine(); - - // Is this a backtrace dump? - if (s.startsWith("#")) { - if (s.startsWith("#0")) { - mDebugger->backtraceModel()->clear(); - } - // Find function name - if (!findAnnotation(AnnotationType::TFrameFunctionName)) - return; - - PTrace trace = std::make_shared(); - trace->funcname = getNextLine(); - - // Find argument list start - if (!findAnnotation(AnnotationType::TFrameArgs)) - return; - - // Arguments are either () or detailed list - s = getNextLine(); - - while (peekNextAnnotation() == AnnotationType::TArgBegin) { - - // argument name - if (!findAnnotation(AnnotationType::TArgBegin)) - return; - - s = s + getNextLine(); - - // = - if (!findAnnotation(AnnotationType::TArgNameEnd)) - return; - s = s + ' ' + getNextLine() + ' '; // should be = - - // argument value - if (!findAnnotation(AnnotationType::TArgValue)) - return; - - s = s + getNextLine(); - - // argument end - if (!findAnnotation(AnnotationType::TArgEnd)) - return; - - s = s + getNextLine(); - } - - trace->funcname = trace->funcname + s.trimmed(); - - // source info - if (peekNextAnnotation() == AnnotationType::TFrameSourceBegin) { - // Find filename - if (!findAnnotation(AnnotationType::TFrameSourceFile)) - return; - trace->filename = getNextLine(); - // find line - if (!findAnnotation(AnnotationType::TFrameSourceLine)) - return; - trace->line = getNextLine().trimmed().toInt(); - } else { - trace->filename = ""; - trace->line = 0; - } - mDebugger->backtraceModel()->addTrace(trace); - - // Skip over the remaining frame part... - if (!findAnnotation(AnnotationType::TFrameEnd)) - return; - - // Not another one coming? Done! - if (peekNextAnnotation() != AnnotationType::TFrameBegin) { - // End of stack trace dump! - dobacktraceready = true; - } - } else - doupdatecpuwindow = true; -} - void DebugReader::handleLocalOutput() { // name(spaces)hexvalue(tab)decimalvalue @@ -1167,9 +1086,22 @@ void DebugReader::processResult(const QByteArray &result) if (!parseOk) return; switch(resultType) { + case GDBMIResultType::BreakpointTable: + case GDBMIResultType::Frame: + case GDBMIResultType::Locals: + break; case GDBMIResultType::Breakpoint: handleBreakpoint(parseValue.object()); return; + case GDBMIResultType::FrameStack: + handleStack(parseValue.array()); + return; + case GDBMIResultType::LocalVariables: + handleLocalVariables(parseValue.array()); + return; + case GDBMIResultType::Evaluation: + handleEvaluation(parseValue.value()); + return; } QByteArray name = result.mid(0,pos); @@ -1227,13 +1159,12 @@ void DebugReader::processExecAsyncRecord(const QByteArray &line) mProcessExited = true; return; } + mUpdateExecution = true; + mUpdateCPUInfo = true; + mBreakPointFile = multiValues["fullname"].pathValue(); + mBreakPointLine = multiValues["line"].intValue(); if (reason == "signal-received") { - //todo: signal received - return; - } - if (reason == "breakpoint-hit") { - //todo: signal received - return; + mSignalReceived = true; } } } @@ -1282,10 +1213,16 @@ void DebugReader::processDebugOutput(const QByteArray& debugOutput) emit parseStarted(); mConsoleOutput.clear(); + mLocalsValue.clear(); + mEvalValue.clear(); + mMemoryValue.clear(); - //try + mUpdateExecution = false; + mSignalReceived = false; + mUpdateCPUInfo = false; + mUpdateLocals = false; + mEvalReady = false; - dobacktraceready = false; dodisassemblerready = false; doregistersready = false; doevalready = false; @@ -1725,12 +1662,58 @@ QStringList DebugReader::tokenize(const QString &s) void DebugReader::handleBreakpoint(const GDBMIResultParser::ParseObject& breakpoint) { // gdb use system encoding for file path - QString filename = QFileInfo(QString::fromLocal8Bit(breakpoint["filename"].value())).absoluteFilePath(); + QString filename = breakpoint["fullname"].value(); int line = breakpoint["line"].intValue(); int number = breakpoint["number"].intValue(); emit breakpointInfoGetted(filename, line , number); } +void DebugReader::handleStack(const QList & stack) +{ + mDebugger->backtraceModel()->clear(); + foreach (const GDBMIResultParser::ParseValue& frameValue, stack) { + GDBMIResultParser::ParseObject frameObject = frameValue.object(); + PTrace trace = std::make_shared(); + trace->funcname = frameObject["func"].value(); + trace->filename = frameObject["fullname"].pathValue(); + trace->line = frameObject["fullname"].intValue(); + trace->level = frameObject["level"].intValue(0); + trace->address = frameObject["addr"].value(); + mDebugger->backtraceModel()->addTrace(trace); + } +} + +void DebugReader::handleLocalVariables(const QList &variables) +{ + mUpdateLocals=true; + foreach (const GDBMIResultParser::ParseValue& varValue, variables) { + GDBMIResultParser::ParseObject varObject = varValue.object(); + mLocalsValue.append(QString("%1 = %2") + .arg(varObject["name"].value(),varObject["value"].value())); + } +} + +void DebugReader::handleEvaluation(const QString &value) +{ + mEvalReady = true; + mEvalValue = value; +} + +void DebugReader::handleMemory(const QList &rows) +{ + mUpdateMemory = true; + foreach (const GDBMIResultParser::ParseValue& row, rows) { + GDBMIResultParser::ParseObject rowObject = row.object(); + QList data = rowObject["data"].array(); + QStringList values; + foreach (const GDBMIResultParser::ParseValue& val, data) { + values.append(val.value()); + } + mLocalsValue.append(QString("%1 %2") + .arg(rowObject["addr"].value(),values.join(" "))); + } +} + QByteArray DebugReader::removeToken(const QByteArray &line) { int p=0; @@ -1746,6 +1729,71 @@ QByteArray DebugReader::removeToken(const QByteArray &line) return line; } +const QStringList &DebugReader::memoryValue() const +{ + return mMemoryValue; +} + +bool DebugReader::updateMemory() const +{ + return mUpdateMemory; +} + +const QString &DebugReader::evalValue() const +{ + return mEvalValue; +} + +bool DebugReader::evalReady() const +{ + return mEvalReady; +} + +const QStringList &DebugReader::localsValue() const +{ + return mLocalsValue; +} + +bool DebugReader::updateLocals() const +{ + return mUpdateLocals; +} + +bool DebugReader::updateCPUInfo() const +{ + return mUpdateCPUInfo; +} + +const PDebugCommand &DebugReader::currentCmd() const +{ + return mCurrentCmd; +} + +const QString &DebugReader::breakPointFile() const +{ + return mBreakPointFile; +} + +int DebugReader::breakPointLine() const +{ + return mBreakPointLine; +} + +const QStringList &DebugReader::consoleOutput() const +{ + return mConsoleOutput; +} + +bool DebugReader::signalReceived() const +{ + return mSignalReceived; +} + +bool DebugReader::updateExecution() const +{ + return mUpdateExecution; +} + bool DebugReader::processExited() const { return mProcessExited; @@ -1791,7 +1839,6 @@ bool DebugReader::waitStart() mStartSemaphore.acquire(1); } - void DebugReader::run() { mStop = false; @@ -2056,6 +2103,7 @@ void BreakpointModel::updateBreakpointNumber(const QString &filename, int line, foreach (PBreakpoint bp, mList) { if (bp->filename == filename && bp->line == line) { bp->number = number; + return; } } } diff --git a/RedPandaIDE/debugger.h b/RedPandaIDE/debugger.h index 3619102a..c92ab62a 100644 --- a/RedPandaIDE/debugger.h +++ b/RedPandaIDE/debugger.h @@ -55,7 +55,9 @@ using PBreakpoint = std::shared_ptr; struct Trace { QString funcname; QString filename; + QString address; int line; + int level; }; using PTrace = std::shared_ptr; @@ -281,6 +283,31 @@ public: bool processExited() const; + bool updateExecution() const; + + bool signalReceived() const; + + const QStringList &consoleOutput() const; + + int breakPointLine() const; + + const QString &breakPointFile() const; + + const PDebugCommand ¤tCmd() const; + + bool updateCPUInfo() const; + + bool updateLocals() const; + + const QStringList &localsValue() const; + + bool evalReady() const; + + const QString &evalValue() const; + + bool updateMemory() const; + + const QStringList &memoryValue() const; signals: void parseStarted(); @@ -302,7 +329,6 @@ private: void handleDisplay(); void handleError(); void handleExit(); - void handleFrames(); void handleLocalOutput(); void handleLocals(); void handleMemory(); @@ -319,6 +345,10 @@ private: QStringList tokenize(const QString& s); void handleBreakpoint(const GDBMIResultParser::ParseObject& breakpoint); + void handleStack(const QList & stack); + void handleLocalVariables(const QList & variables); + void handleEvaluation(const QString& value); + void handleMemory(const QList & rows); void processConsoleOutput(const QByteArray& line); void processResult(const QByteArray& result); void processExecAsyncRecord(const QByteArray& line); @@ -345,16 +375,11 @@ private: //fWatchView: TTreeView; int mIndex; - int mBreakPointLine; - QString mBreakPointFile; - QString mEvalValue; - QStringList mMemoryValue; - QStringList mLocalsValue; + QString mSignal; bool mUseUTF8; // attempt to cut down on Synchronize calls - bool dobacktraceready; bool dodisassemblerready; bool doregistersready; bool doevalready; @@ -363,12 +388,24 @@ private: bool doreceivedsignal; bool doreceivedsfwarning; bool doupdatememoryview; - bool doupdatelocal; // bool mInferiorPaused; bool mProcessExited; + + bool mUpdateExecution; + bool mSignalReceived; + bool mUpdateCPUInfo; + bool mUpdateLocals; + bool mEvalReady; + bool mUpdateMemory; + QStringList mConsoleOutput; + int mBreakPointLine; + QString mBreakPointFile; + QStringList mLocalsValue; + QString mEvalValue; + QStringList mMemoryValue; bool mStop; // QThread interface diff --git a/RedPandaIDE/gdbmiresultparser.cpp b/RedPandaIDE/gdbmiresultparser.cpp index 4a0620c4..cba4e8a3 100644 --- a/RedPandaIDE/gdbmiresultparser.cpp +++ b/RedPandaIDE/gdbmiresultparser.cpp @@ -1,5 +1,6 @@ #include "gdbmiresultparser.h" +#include #include GDBMIResultParser::GDBMIResultParser() @@ -172,7 +173,7 @@ bool GDBMIResultParser::parseObject(const char *&p, ParseObject &obj) return false; } -bool GDBMIResultParser::parseArray(const char *&p, QList &array) +bool GDBMIResultParser::parseArray(const char *&p, QList &array) { if (*p!='[') return false; @@ -180,10 +181,10 @@ bool GDBMIResultParser::parseArray(const char *&p, QList &GDBMIResultParser::ParseValue::array() const +const QList<::GDBMIResultParser::ParseValue> &GDBMIResultParser::ParseValue::array() const { Q_ASSERT(mType == ParseValueType::Array); return mArray; @@ -259,6 +260,12 @@ int GDBMIResultParser::ParseValue::intValue(int defaultValue) const return defaultValue; } +QString GDBMIResultParser::ParseValue::pathValue() const +{ + Q_ASSERT(mType == ParseValueType::Value); + return QFileInfo(QString::fromLocal8Bit(mValue)).absoluteFilePath(); +} + GDBMIResultParser::ParseValueType GDBMIResultParser::ParseValue::type() const { return mType; @@ -281,7 +288,7 @@ GDBMIResultParser::ParseValue::ParseValue(const ParseObject &object): { } -GDBMIResultParser::ParseValue::ParseValue(const QList &array): +GDBMIResultParser::ParseValue::ParseValue(const QList &array): mArray(array), mType(ParseValueType::Array) { @@ -301,7 +308,7 @@ GDBMIResultParser::ParseValue &GDBMIResultParser::ParseValue::operator=(const Pa mObject = object; } -GDBMIResultParser::ParseValue &GDBMIResultParser::ParseValue::operator=(const QList& array) +GDBMIResultParser::ParseValue &GDBMIResultParser::ParseValue::operator=(const QList& array) { Q_ASSERT(mType == ParseValueType::NotAssigned); mType = ParseValueType::Array; diff --git a/RedPandaIDE/gdbmiresultparser.h b/RedPandaIDE/gdbmiresultparser.h index 4ae71eb4..a895c73f 100644 --- a/RedPandaIDE/gdbmiresultparser.h +++ b/RedPandaIDE/gdbmiresultparser.h @@ -48,20 +48,21 @@ public: explicit ParseValue(); explicit ParseValue(const QByteArray& value); explicit ParseValue(const ParseObject &object); - explicit ParseValue(const QList& array); + explicit ParseValue(const QList& array); ParseValue(const ParseValue&) = delete; const QByteArray &value() const; - const QList &array() const; + const QList &array() const; const ParseObject &object() const; int intValue(int defaultValue=-1) const; + QString pathValue() const; ParseValueType type() const; ParseValue& operator=(const QByteArray& value); ParseValue& operator=(const ParseObject& object); - ParseValue& operator=(const QList& array); + ParseValue& operator=(const QList& array); ParseValue& operator=(const ParseValue& value); private: QByteArray mValue; - QList mArray; + QList mArray; ParseObject mObject; ParseValueType mType; }; @@ -78,7 +79,7 @@ private: bool parseValue(const char* &p, ParseValue& value); bool parseStringValue(const char*&p, QByteArray& stringValue); bool parseObject(const char*&p, ParseObject& obj); - bool parseArray(const char*&p, QList& array); + bool parseArray(const char*&p, QList& array); void skipSpaces(const char* &p); bool isNameChar(char ch); bool isSpaceChar(char ch);