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;
}