diff --git a/NEWS.md b/NEWS.md index 257d791a..76d07d6b 100644 --- a/NEWS.md +++ b/NEWS.md @@ -42,8 +42,7 @@ Red Panda C++ Version 2.27 - enhancement: Support "enum struct" Scoped enumerations. - fix: Function tips contains functions that not in the scope. - fix: Hint for bold text () are not correctly handled in the function tips. - - + - enhancement: Improve lldb-mi compatibility. Red Panda C++ Version 2.26 - enhancement: Code suggestion for embedded std::vectors. diff --git a/RedPandaIDE/debugger/debugger.cpp b/RedPandaIDE/debugger/debugger.cpp index 25dcf0b3..6d1c6590 100644 --- a/RedPandaIDE/debugger/debugger.cpp +++ b/RedPandaIDE/debugger/debugger.cpp @@ -98,7 +98,7 @@ bool Debugger::startClient(int compilerSetIndex, else setDebuggerType(DebuggerType::GDB); // force to lldb-server if using lldb-mi, which creates new console but does not bind inferior’s stdio to the new console on Windows. - setUseDebugServer(pSettings->debugger().useGDBServer() || debuggerType() == DebuggerType::LLDB_MI); + setUseDebugServer(pSettings->debugger().useGDBServer()); mExecuting = true; QString debuggerPath = compilerSet->debugger(); //QFile debuggerProgram(debuggerPath); diff --git a/RedPandaIDE/debugger/gdbmidebugger.cpp b/RedPandaIDE/debugger/gdbmidebugger.cpp index 633793be..bd3894af 100644 --- a/RedPandaIDE/debugger/gdbmidebugger.cpp +++ b/RedPandaIDE/debugger/gdbmidebugger.cpp @@ -123,6 +123,11 @@ void GDBMIDebuggerClient::run() break; } if (mStop) { + mProcess->readAll(); + mProcess->write("quit\n"); + msleep(50); + mProcess->readAll(); + msleep(50); mProcess->terminate(); mProcess->kill(); break; @@ -135,8 +140,8 @@ void GDBMIDebuggerClient::run() if (readed.endsWith("\n")&& outputTerminated(buffer)) { processDebugOutput(buffer); buffer.clear(); - mCmdRunning = false; - runNextCmd(); + // mCmdRunning = false; + // runNextCmd(); } else if (!mCmdRunning && readed.isEmpty()){ runNextCmd(); } else if (readed.isEmpty()){ @@ -191,7 +196,7 @@ void GDBMIDebuggerClient::runNextCmd() } if (pCmd->command == "-var-create") { //hack for variable creation,to easy remember var expression - if (debugger()->debuggerType()==DebuggerType::LLDB_MI) + if (clientType()==DebuggerType::LLDB_MI) params = " - * "+params; else params = " - @ "+params; @@ -407,6 +412,40 @@ void GDBMIDebuggerClient::handleMemory(const QList &rows) +{ + QStringList memory; + foreach (const GDBMIResultParser::ParseValue& row, rows) { + GDBMIResultParser::ParseObject rowObject = row.object(); + bool ok; + qulonglong startAddr = rowObject["begin"].value().toLongLong(&ok, 16); + qulonglong endAddr = rowObject["end"].value().toLongLong(&ok, 16); + qulonglong offset = rowObject["offset"].value().toLongLong(&ok, 16); + startAddr += offset; + QByteArray contents = rowObject["contents"].value(); + qulonglong addr = startAddr; + QStringList values; + int cols = pSettings->debugger().memoryViewColumns(); + while (addr &names) { QStringList nameList; @@ -611,40 +650,43 @@ void GDBMIDebuggerClient::processResult(const QByteArray &result) break; case GDBMIResultType::Breakpoint: handleBreakpoint(multiValues["bkpt"].object()); - return; + break; case GDBMIResultType::Frame: handleFrame(multiValues["frame"]); - return; + break; case GDBMIResultType::FrameStack: handleStack(multiValues["stack"].array()); - return; + break; case GDBMIResultType::LocalVariables: handleLocalVariables(multiValues["variables"].array()); - return; + break; case GDBMIResultType::Evaluation: handleEvaluation(multiValues["value"].value()); - return; + break; case GDBMIResultType::Memory: handleMemory(multiValues["memory"].array()); - return; + break; + case GDBMIResultType::MemoryBytes: + handleMemoryBytes(multiValues["memory"].array()); + break; case GDBMIResultType::RegisterNames: handleRegisterNames(multiValues["register-names"].array()); - return; + break; case GDBMIResultType::RegisterValues: handleRegisterValue(multiValues["register-values"].array()); - return; + break; case GDBMIResultType::CreateVar: handleCreateVar(multiValues); - return; + break; case GDBMIResultType::ListVarChildren: handleListVarChildren(multiValues); - return; + break; case GDBMIResultType::UpdateVarValue: handleUpdateVarValue(multiValues["changelist"].array()); - return; + break; default: - return; - } + break; + } } void GDBMIDebuggerClient::processExecAsyncRecord(const QByteArray &line) @@ -734,6 +776,13 @@ void GDBMIDebuggerClient::processError(const QByteArray &errorLine) void GDBMIDebuggerClient::processResultRecord(const QByteArray &line) { + auto action = finally([this]() { + if (!mProcessExited) { + mCmdRunning = false; + runNextCmd(); + } + }); + if (line.startsWith("^exit")) { mProcessExited = true; return; @@ -879,7 +928,6 @@ void GDBMIDebuggerClient::initialize(const QString& inferior, bool hasSymbols) { postCommand("-gdb-set", "mi-async on"); postCommand("-enable-pretty-printing",""); - postCommand("-data-list-register-names",""); postCommand("-gdb-set", "width 0"); // don't wrap output, very annoying postCommand("-gdb-set", "confirm off"); postCommand("-gdb-set", "print repeats 10"); @@ -913,12 +961,20 @@ void GDBMIDebuggerClient::runInferior(bool hasBreakpoints) if (pSettings->executor().useParams()) { postCommand("-exec-arguments", pSettings->executor().params()); } - if (!hasBreakpoints) { - postCommand("-exec-run","--start"); - } else { + if (clientType() == DebuggerType::LLDB_MI) { + if (!hasBreakpoints) { + postCommand("-break-insert","-t main"); + } postCommand("-exec-run",""); + } else { + if (!hasBreakpoints) { + postCommand("-exec-run","--start"); + } else { + postCommand("-exec-run",""); + } } } + postCommand("-data-list-register-names",""); } void GDBMIDebuggerClient::stepOver() @@ -970,10 +1026,13 @@ void GDBMIDebuggerClient::refreshStackVariables() void GDBMIDebuggerClient::readMemory(const QString& startAddress, int rows, int cols) { - postCommand("-data-read-memory",QString("%1 x 1 %2 %3 ") + // postCommand("-data-read-memory",QString("%1 x 1 %2 %3 ") + // .arg(startAddress) + // .arg(rows) + // .arg(cols)); + postCommand("-data-read-memory-bytes",QString("%1 %2") .arg(startAddress) - .arg(rows) - .arg(cols)); + .arg(rows * cols)); } void GDBMIDebuggerClient::writeMemory(qulonglong address, unsigned char data) diff --git a/RedPandaIDE/debugger/gdbmidebugger.h b/RedPandaIDE/debugger/gdbmidebugger.h index a52f035f..9fb88e9d 100644 --- a/RedPandaIDE/debugger/gdbmidebugger.h +++ b/RedPandaIDE/debugger/gdbmidebugger.h @@ -103,6 +103,7 @@ private: void handleLocalVariables(const QList & variables); void handleEvaluation(const QString& value); void handleMemory(const QList & rows); + void handleMemoryBytes(const QList & rows); void handleRegisterNames(const QList & names); void handleRegisterValue(const QList & values); void handleListVarChildren(const GDBMIResultParser::ParseObject& multiVars); diff --git a/RedPandaIDE/debugger/gdbmiresultparser.cpp b/RedPandaIDE/debugger/gdbmiresultparser.cpp index b6d51c20..9244fee4 100644 --- a/RedPandaIDE/debugger/gdbmiresultparser.cpp +++ b/RedPandaIDE/debugger/gdbmiresultparser.cpp @@ -32,6 +32,7 @@ GDBMIResultParser::GDBMIResultParser() // mResultTypes.insert("register-names",GDBMIResultType::RegisterNames); // mResultTypes.insert("register-values",GDBMIResultType::RegisterValues); mResultTypes.insert("-data-read-memory",GDBMIResultType::Memory); + mResultTypes.insert("-data-read-memory-bytes",GDBMIResultType::MemoryBytes); mResultTypes.insert("-data-list-register-names",GDBMIResultType::RegisterNames); mResultTypes.insert("-data-list-register-values",GDBMIResultType::RegisterValues); mResultTypes.insert("-var-create",GDBMIResultType::CreateVar); diff --git a/RedPandaIDE/debugger/gdbmiresultparser.h b/RedPandaIDE/debugger/gdbmiresultparser.h index 7bfec00c..dfe0eb20 100644 --- a/RedPandaIDE/debugger/gdbmiresultparser.h +++ b/RedPandaIDE/debugger/gdbmiresultparser.h @@ -35,6 +35,7 @@ enum class GDBMIResultType { RegisterNames, RegisterValues, Memory, + MemoryBytes, CreateVar, ListVarChildren, UpdateVarValue diff --git a/RedPandaIDE/mainwindow.cpp b/RedPandaIDE/mainwindow.cpp index 16b8e4dc..7212be8b 100644 --- a/RedPandaIDE/mainwindow.cpp +++ b/RedPandaIDE/mainwindow.cpp @@ -1101,7 +1101,7 @@ void MainWindow::setActiveBreakpoint(QString fileName, int Line, bool setFocus) activateWindow(); } } else { - showCPUInfoDialog(); + // showCPUInfoDialog(); } return; }