- 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.
- 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.
- enhancement: Improve lldb-mi compatibility.
Red Panda C++ Version 2.26
- enhancement: Code suggestion for embedded std::vectors.

View File

@ -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 inferiors 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);

View File

@ -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<GDBMIResultParser::ParseValue
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)
{
QStringList nameList;
@ -611,39 +650,42 @@ 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;
}
}
@ -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)

View File

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

View File

@ -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);

View File

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

View File

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