- enhancement: improve lldb-mi compatibility.

This commit is contained in:
Roy Qu 2024-03-11 13:13:53 +08:00
parent 9cb980f2f6
commit 35d6b4d014
7 changed files with 88 additions and 27 deletions

View File

@ -42,8 +42,7 @@ Red Panda C++ Version 2.27
- enhancement: Support "enum struct" Scoped enumerations. - enhancement: Support "enum struct" Scoped enumerations.
- fix: Function tips contains functions that not in the scope. - fix: Function tips contains functions that not in the scope.
- fix: Hint for bold text (<b></b>) are not correctly handled in the function tips. - fix: Hint for bold text (<b></b>) are not correctly handled in the function tips.
- enhancement: Improve lldb-mi compatibility.
Red Panda C++ Version 2.26 Red Panda C++ Version 2.26
- enhancement: Code suggestion for embedded std::vectors. - enhancement: Code suggestion for embedded std::vectors.

View File

@ -98,7 +98,7 @@ bool Debugger::startClient(int compilerSetIndex,
else else
setDebuggerType(DebuggerType::GDB); setDebuggerType(DebuggerType::GDB);
// force to lldb-server if using lldb-mi, which creates new console but does not bind inferiors stdio to the new console on Windows. // force to lldb-server if using lldb-mi, which creates new console but does not bind inferiors stdio to the new console on Windows.
setUseDebugServer(pSettings->debugger().useGDBServer() || debuggerType() == DebuggerType::LLDB_MI); setUseDebugServer(pSettings->debugger().useGDBServer());
mExecuting = true; mExecuting = true;
QString debuggerPath = compilerSet->debugger(); QString debuggerPath = compilerSet->debugger();
//QFile debuggerProgram(debuggerPath); //QFile debuggerProgram(debuggerPath);

View File

@ -123,6 +123,11 @@ void GDBMIDebuggerClient::run()
break; break;
} }
if (mStop) { if (mStop) {
mProcess->readAll();
mProcess->write("quit\n");
msleep(50);
mProcess->readAll();
msleep(50);
mProcess->terminate(); mProcess->terminate();
mProcess->kill(); mProcess->kill();
break; break;
@ -135,8 +140,8 @@ void GDBMIDebuggerClient::run()
if (readed.endsWith("\n")&& outputTerminated(buffer)) { if (readed.endsWith("\n")&& outputTerminated(buffer)) {
processDebugOutput(buffer); processDebugOutput(buffer);
buffer.clear(); buffer.clear();
mCmdRunning = false; // mCmdRunning = false;
runNextCmd(); // runNextCmd();
} else if (!mCmdRunning && readed.isEmpty()){ } else if (!mCmdRunning && readed.isEmpty()){
runNextCmd(); runNextCmd();
} else if (readed.isEmpty()){ } else if (readed.isEmpty()){
@ -191,7 +196,7 @@ void GDBMIDebuggerClient::runNextCmd()
} }
if (pCmd->command == "-var-create") { if (pCmd->command == "-var-create") {
//hack for variable creation,to easy remember var expression //hack for variable creation,to easy remember var expression
if (debugger()->debuggerType()==DebuggerType::LLDB_MI) if (clientType()==DebuggerType::LLDB_MI)
params = " - * "+params; params = " - * "+params;
else else
params = " - @ "+params; params = " - @ "+params;
@ -407,6 +412,40 @@ void GDBMIDebuggerClient::handleMemory(const QList<GDBMIResultParser::ParseValue
emit memoryUpdated(memory); emit memoryUpdated(memory);
} }
void GDBMIDebuggerClient::handleMemoryBytes(const QList<GDBMIResultParser::ParseValue> &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<endAddr) {
values.append("0x"+contents.mid((addr-startAddr)*2,2));
if ((addr-startAddr+1)%cols == 0) {
memory.append(QString("%1 %2").arg(
QString("0x%1").arg(addr - cols + 1 ,0,16),
values.join(" ")));
values.clear();
}
addr++;
}
if (!values.isEmpty()) {
memory.append(QString("%1 %2").arg(
QString("0x%1").arg(addr - values.length() + 1 ,0,16),
values.join(" ")));
values.clear();
}
}
emit memoryUpdated(memory);
}
void GDBMIDebuggerClient::handleRegisterNames(const QList<GDBMIResultParser::ParseValue> &names) void GDBMIDebuggerClient::handleRegisterNames(const QList<GDBMIResultParser::ParseValue> &names)
{ {
QStringList nameList; QStringList nameList;
@ -611,39 +650,42 @@ void GDBMIDebuggerClient::processResult(const QByteArray &result)
break; break;
case GDBMIResultType::Breakpoint: case GDBMIResultType::Breakpoint:
handleBreakpoint(multiValues["bkpt"].object()); handleBreakpoint(multiValues["bkpt"].object());
return; break;
case GDBMIResultType::Frame: case GDBMIResultType::Frame:
handleFrame(multiValues["frame"]); handleFrame(multiValues["frame"]);
return; break;
case GDBMIResultType::FrameStack: case GDBMIResultType::FrameStack:
handleStack(multiValues["stack"].array()); handleStack(multiValues["stack"].array());
return; break;
case GDBMIResultType::LocalVariables: case GDBMIResultType::LocalVariables:
handleLocalVariables(multiValues["variables"].array()); handleLocalVariables(multiValues["variables"].array());
return; break;
case GDBMIResultType::Evaluation: case GDBMIResultType::Evaluation:
handleEvaluation(multiValues["value"].value()); handleEvaluation(multiValues["value"].value());
return; break;
case GDBMIResultType::Memory: case GDBMIResultType::Memory:
handleMemory(multiValues["memory"].array()); handleMemory(multiValues["memory"].array());
return; break;
case GDBMIResultType::MemoryBytes:
handleMemoryBytes(multiValues["memory"].array());
break;
case GDBMIResultType::RegisterNames: case GDBMIResultType::RegisterNames:
handleRegisterNames(multiValues["register-names"].array()); handleRegisterNames(multiValues["register-names"].array());
return; break;
case GDBMIResultType::RegisterValues: case GDBMIResultType::RegisterValues:
handleRegisterValue(multiValues["register-values"].array()); handleRegisterValue(multiValues["register-values"].array());
return; break;
case GDBMIResultType::CreateVar: case GDBMIResultType::CreateVar:
handleCreateVar(multiValues); handleCreateVar(multiValues);
return; break;
case GDBMIResultType::ListVarChildren: case GDBMIResultType::ListVarChildren:
handleListVarChildren(multiValues); handleListVarChildren(multiValues);
return; break;
case GDBMIResultType::UpdateVarValue: case GDBMIResultType::UpdateVarValue:
handleUpdateVarValue(multiValues["changelist"].array()); handleUpdateVarValue(multiValues["changelist"].array());
return; break;
default: default:
return; break;
} }
} }
@ -734,6 +776,13 @@ void GDBMIDebuggerClient::processError(const QByteArray &errorLine)
void GDBMIDebuggerClient::processResultRecord(const QByteArray &line) void GDBMIDebuggerClient::processResultRecord(const QByteArray &line)
{ {
auto action = finally([this]() {
if (!mProcessExited) {
mCmdRunning = false;
runNextCmd();
}
});
if (line.startsWith("^exit")) { if (line.startsWith("^exit")) {
mProcessExited = true; mProcessExited = true;
return; return;
@ -879,7 +928,6 @@ void GDBMIDebuggerClient::initialize(const QString& inferior, bool hasSymbols)
{ {
postCommand("-gdb-set", "mi-async on"); postCommand("-gdb-set", "mi-async on");
postCommand("-enable-pretty-printing",""); postCommand("-enable-pretty-printing","");
postCommand("-data-list-register-names","");
postCommand("-gdb-set", "width 0"); // don't wrap output, very annoying postCommand("-gdb-set", "width 0"); // don't wrap output, very annoying
postCommand("-gdb-set", "confirm off"); postCommand("-gdb-set", "confirm off");
postCommand("-gdb-set", "print repeats 10"); postCommand("-gdb-set", "print repeats 10");
@ -913,6 +961,12 @@ void GDBMIDebuggerClient::runInferior(bool hasBreakpoints)
if (pSettings->executor().useParams()) { if (pSettings->executor().useParams()) {
postCommand("-exec-arguments", pSettings->executor().params()); postCommand("-exec-arguments", pSettings->executor().params());
} }
if (clientType() == DebuggerType::LLDB_MI) {
if (!hasBreakpoints) {
postCommand("-break-insert","-t main");
}
postCommand("-exec-run","");
} else {
if (!hasBreakpoints) { if (!hasBreakpoints) {
postCommand("-exec-run","--start"); postCommand("-exec-run","--start");
} else { } else {
@ -920,6 +974,8 @@ void GDBMIDebuggerClient::runInferior(bool hasBreakpoints)
} }
} }
} }
postCommand("-data-list-register-names","");
}
void GDBMIDebuggerClient::stepOver() void GDBMIDebuggerClient::stepOver()
{ {
@ -970,10 +1026,13 @@ void GDBMIDebuggerClient::refreshStackVariables()
void GDBMIDebuggerClient::readMemory(const QString& startAddress, int rows, int cols) 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(startAddress)
.arg(rows) .arg(rows * cols));
.arg(cols));
} }
void GDBMIDebuggerClient::writeMemory(qulonglong address, unsigned char data) void GDBMIDebuggerClient::writeMemory(qulonglong address, unsigned char data)

View File

@ -103,6 +103,7 @@ private:
void handleLocalVariables(const QList<GDBMIResultParser::ParseValue> & variables); void handleLocalVariables(const QList<GDBMIResultParser::ParseValue> & variables);
void handleEvaluation(const QString& value); void handleEvaluation(const QString& value);
void handleMemory(const QList<GDBMIResultParser::ParseValue> & rows); void handleMemory(const QList<GDBMIResultParser::ParseValue> & rows);
void handleMemoryBytes(const QList<GDBMIResultParser::ParseValue> & rows);
void handleRegisterNames(const QList<GDBMIResultParser::ParseValue> & names); void handleRegisterNames(const QList<GDBMIResultParser::ParseValue> & names);
void handleRegisterValue(const QList<GDBMIResultParser::ParseValue> & values); void handleRegisterValue(const QList<GDBMIResultParser::ParseValue> & values);
void handleListVarChildren(const GDBMIResultParser::ParseObject& multiVars); void handleListVarChildren(const GDBMIResultParser::ParseObject& multiVars);

View File

@ -32,6 +32,7 @@ GDBMIResultParser::GDBMIResultParser()
// mResultTypes.insert("register-names",GDBMIResultType::RegisterNames); // mResultTypes.insert("register-names",GDBMIResultType::RegisterNames);
// mResultTypes.insert("register-values",GDBMIResultType::RegisterValues); // mResultTypes.insert("register-values",GDBMIResultType::RegisterValues);
mResultTypes.insert("-data-read-memory",GDBMIResultType::Memory); 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-names",GDBMIResultType::RegisterNames);
mResultTypes.insert("-data-list-register-values",GDBMIResultType::RegisterValues); mResultTypes.insert("-data-list-register-values",GDBMIResultType::RegisterValues);
mResultTypes.insert("-var-create",GDBMIResultType::CreateVar); mResultTypes.insert("-var-create",GDBMIResultType::CreateVar);

View File

@ -35,6 +35,7 @@ enum class GDBMIResultType {
RegisterNames, RegisterNames,
RegisterValues, RegisterValues,
Memory, Memory,
MemoryBytes,
CreateVar, CreateVar,
ListVarChildren, ListVarChildren,
UpdateVarValue UpdateVarValue

View File

@ -1101,7 +1101,7 @@ void MainWindow::setActiveBreakpoint(QString fileName, int Line, bool setFocus)
activateWindow(); activateWindow();
} }
} else { } else {
showCPUInfoDialog(); // showCPUInfoDialog();
} }
return; return;
} }