- enhancement: improve lldb-mi compatibility.
This commit is contained in:
parent
9cb980f2f6
commit
35d6b4d014
3
NEWS.md
3
NEWS.md
|
@ -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.
|
||||||
|
|
|
@ -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 inferior’s stdio to the new console on Windows.
|
// 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;
|
mExecuting = true;
|
||||||
QString debuggerPath = compilerSet->debugger();
|
QString debuggerPath = compilerSet->debugger();
|
||||||
//QFile debuggerProgram(debuggerPath);
|
//QFile debuggerProgram(debuggerPath);
|
||||||
|
|
|
@ -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,12 +961,20 @@ 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 (!hasBreakpoints) {
|
if (clientType() == DebuggerType::LLDB_MI) {
|
||||||
postCommand("-exec-run","--start");
|
if (!hasBreakpoints) {
|
||||||
} else {
|
postCommand("-break-insert","-t main");
|
||||||
|
}
|
||||||
postCommand("-exec-run","");
|
postCommand("-exec-run","");
|
||||||
|
} else {
|
||||||
|
if (!hasBreakpoints) {
|
||||||
|
postCommand("-exec-run","--start");
|
||||||
|
} else {
|
||||||
|
postCommand("-exec-run","");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
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)
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -35,6 +35,7 @@ enum class GDBMIResultType {
|
||||||
RegisterNames,
|
RegisterNames,
|
||||||
RegisterValues,
|
RegisterValues,
|
||||||
Memory,
|
Memory,
|
||||||
|
MemoryBytes,
|
||||||
CreateVar,
|
CreateVar,
|
||||||
ListVarChildren,
|
ListVarChildren,
|
||||||
UpdateVarValue
|
UpdateVarValue
|
||||||
|
|
|
@ -1101,7 +1101,7 @@ void MainWindow::setActiveBreakpoint(QString fileName, int Line, bool setFocus)
|
||||||
activateWindow();
|
activateWindow();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
showCPUInfoDialog();
|
// showCPUInfoDialog();
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue