Debugger: DAPEngine improve breakpoints handling

- Added proper "Insert" breakpoint
- Added proper "Remove" breakpoint
- Fixed errors with engine states after pause and continue

Change-Id: Icbe1b4cf549cee633809d0a1c9ab19dbf877dbf0
Reviewed-by: <github-actions-qt-creator@cristianadam.eu>
Reviewed-by: hjk <hjk@qt.io>
This commit is contained in:
Artem Sokolovskii
2023-04-06 14:20:01 +02:00
parent 6932c6ca23
commit cbaeee89d6
2 changed files with 114 additions and 44 deletions

View File

@@ -50,7 +50,7 @@ DapEngine::DapEngine()
setDebuggerName("DAP"); setDebuggerName("DAP");
} }
void DapEngine::executeDebuggerCommand(const QString &command) void DapEngine::executeDebuggerCommand(const QString &/*command*/)
{ {
QTC_ASSERT(state() == InferiorStopOk, qDebug() << state()); QTC_ASSERT(state() == InferiorStopOk, qDebug() << state());
// if (state() == DebuggerNotReady) { // if (state() == DebuggerNotReady) {
@@ -183,9 +183,6 @@ void DapEngine::handleDabLaunch()
QJsonObject{ QJsonObject{
{"noDebug", false}, {"noDebug", false},
{"program", runParameters().inferior.command.executable().path()}, {"program", runParameters().inferior.command.executable().path()},
// {"args", runParameters().inferior.command.arguments()},
// {"cwd", runParameters().inferior.workingDirectory},
// {"env", QJsonObject::fromVariantMap(runParameters().inferior.environment.toStringMap())}
{"__restart", ""} {"__restart", ""}
}}}); }}});
qDebug() << "handleDabLaunch"; qDebug() << "handleDabLaunch";
@@ -193,24 +190,22 @@ void DapEngine::handleDabLaunch()
void DapEngine::interruptInferior() void DapEngine::interruptInferior()
{ {
QString error;
postDirectCommand({{"command", "pause"}, postDirectCommand({{"command", "pause"},
{"type", "request"}}); {"type", "request"}});
qDebug() << "DapEngine::interruptInferior()";
// interruptProcess(m_proc.processId(), GdbEngineType, &error);
// notifyInferiorExited();
notifyInferiorStopOk();
} }
void DapEngine::executeStepIn(bool) void DapEngine::executeStepIn(bool)
{ {
notifyInferiorRunRequested(); notifyInferiorRunRequested();
// postDirectCommand({{"command", "stepIn"},
// {"type", "request"},
// {"arguments",
// QJsonObject{
// {"threadId", 1}, // The ID of the client using this adapter.
// }}});
notifyInferiorRunOk(); notifyInferiorRunOk();
// postDirectCommand("step");
} }
void DapEngine::executeStepOut() void DapEngine::executeStepOut()
@@ -229,19 +224,13 @@ void DapEngine::executeStepOver(bool)
void DapEngine::continueInferior() void DapEngine::continueInferior()
{ {
notifyInferiorRunRequested();
postDirectCommand({{"command", "continue"}, postDirectCommand({{"command", "continue"},
{"type", "request"}, {"type", "request"},
{"arguments", {"arguments",
QJsonObject{ QJsonObject{
{"threadId", 1}, // The ID of the client using this adapter. {"threadId", 1}, // The ID of the client using this adapter.
}}}); }}});
qDebug() << "continueInferior";
// notifyInferiorRunRequested();
// notifyInferiorRunOk();
// Callback will be triggered e.g. when breakpoint is hit.
// postDirectCommand("continue");
} }
void DapEngine::executeRunToLine(const ContextData &data) void DapEngine::executeRunToLine(const ContextData &data)
@@ -284,36 +273,57 @@ bool DapEngine::acceptsBreakpoint(const BreakpointParameters &) const
return true; // FIXME: Too bold. return true; // FIXME: Too bold.
} }
static QJsonObject createBreakpoint(const Breakpoint &breakpoint)
{
const BreakpointParameters &params = breakpoint->requestedParameters();
if (params.fileName.isEmpty())
return QJsonObject();
QJsonObject bp;
bp["line"] = params.lineNumber;
bp["source"] = QJsonObject{{"name", params.fileName.fileName()},
{"path", params.fileName.path()}};
return bp;
}
void DapEngine::insertBreakpoint(const Breakpoint &bp) void DapEngine::insertBreakpoint(const Breakpoint &bp)
{ {
QTC_ASSERT(bp, return); QTC_ASSERT(bp, return);
QTC_CHECK(bp->state() == BreakpointInsertionRequested); QTC_CHECK(bp->state() == BreakpointInsertionRequested);
notifyBreakpointInsertProceeding(bp); notifyBreakpointInsertProceeding(bp);
QString loc;
const BreakpointParameters &params = bp->requestedParameters(); const BreakpointParameters &params = bp->requestedParameters();
if (params.type == BreakpointByFunction) bp->setResponseId(QString::number(m_nextBreakpointId++));
loc = params.functionName;
else QJsonArray breakpoints;
loc = params.fileName.toString() + ':' + QString::number(params.lineNumber); for (const auto &breakpoint : breakHandler()->breakpoints()) {
QJsonObject jsonBp = createBreakpoint(breakpoint);
if (!jsonBp.isEmpty()
&& params.fileName.path() == jsonBp["source"].toObject()["path"].toString()) {
breakpoints.append(jsonBp);
}
}
postDirectCommand( postDirectCommand(
{{"command", "setBreakpoints"}, {{"command", "setBreakpoints"},
{"type", "request"}, {"type", "request"},
{"arguments", {"arguments",
QJsonObject{{"source", QJsonObject{{"path", params.fileName.toString()}}}, QJsonObject{{"source", QJsonObject{{"path", params.fileName.path()}}},
{"breakpoints", {"breakpoints", breakpoints}
QJsonArray{QJsonObject{{"id", 1}, {"line", params.lineNumber}}}}
}}}); }}});
qDebug() << "insertBreakpoint" << bp->modelId() << bp->responseId();
} }
void DapEngine::updateBreakpoint(const Breakpoint &bp) void DapEngine::updateBreakpoint(const Breakpoint &bp)
{ {
notifyBreakpointChangeProceeding(bp);
// QTC_ASSERT(bp, return); // QTC_ASSERT(bp, return);
// const BreakpointState state = bp->state(); // const BreakpointState state = bp->state();
// if (QTC_GUARD(state == BreakpointUpdateRequested)) // if (QTC_GUARD(state == BreakpointUpdateRequested))
// notifyBreakpointChangeProceeding(bp);
// if (bp->responseId().isEmpty()) // FIXME postpone update somehow (QTimer::singleShot?) // if (bp->responseId().isEmpty()) // FIXME postpone update somehow (QTimer::singleShot?)
// return; // return;
@@ -334,16 +344,25 @@ void DapEngine::removeBreakpoint(const Breakpoint &bp)
{ {
QTC_ASSERT(bp, return); QTC_ASSERT(bp, return);
QTC_CHECK(bp->state() == BreakpointRemoveRequested); QTC_CHECK(bp->state() == BreakpointRemoveRequested);
// notifyBreakpointRemoveProceeding(bp); notifyBreakpointRemoveProceeding(bp);
const BreakpointParameters &params = bp->requestedParameters(); const BreakpointParameters &params = bp->requestedParameters();
QJsonArray breakpoints;
for (const auto &breakpoint : breakHandler()->breakpoints())
if (breakpoint->responseId() != bp->responseId()
&& params.fileName == breakpoint->requestedParameters().fileName) {
QJsonObject jsonBp = createBreakpoint(breakpoint);
breakpoints.append(jsonBp);
}
postDirectCommand({{"command", "setBreakpoints"}, postDirectCommand({{"command", "setBreakpoints"},
{"type", "request"}, {"type", "request"},
{"arguments", {"arguments",
QJsonObject{{"source", QJsonObject{{"path", params.fileName.toString()}}}, QJsonObject{{"source", QJsonObject{{"path", params.fileName.path()}}},
{"breakpoints", QJsonArray{}}}}}); {"breakpoints", breakpoints}}}});
qDebug() << "removeBreakpoint";
// notifyBreakpointRemoveOk(bp); qDebug() << "removeBreakpoint" << bp->modelId() << bp->responseId();
} }
void DapEngine::loadSymbols(const Utils::FilePath &/*moduleName*/) void DapEngine::loadSymbols(const Utils::FilePath &/*moduleName*/)
@@ -431,7 +450,7 @@ bool DapEngine::canHandleToolTip(const DebuggerToolTipContext &) const
return state() == InferiorStopOk; return state() == InferiorStopOk;
} }
void DapEngine::assignValueInDebugger(WatchItem *, const QString &expression, const QVariant &value) void DapEngine::assignValueInDebugger(WatchItem *, const QString &/*expression*/, const QVariant &/*value*/)
{ {
//DebuggerCommand cmd("assignValue"); //DebuggerCommand cmd("assignValue");
//cmd.arg("expression", expression); //cmd.arg("expression", expression);
@@ -555,8 +574,6 @@ void DapEngine::handleOutput(const QJsonDocument &data)
showMessage("configurationDone", LogDebug); showMessage("configurationDone", LogDebug);
qDebug() << "configurationDone success"; qDebug() << "configurationDone success";
notifyInferiorRunOk(); notifyInferiorRunOk();
claimInitialBreakpoints();
return; return;
} }
@@ -571,8 +588,9 @@ void DapEngine::handleOutput(const QJsonDocument &data)
if (type == "event") { if (type == "event") {
const QString event = ob.value("event").toString(); const QString event = ob.value("event").toString();
if (event == "output") {
const QJsonObject body = ob.value("body").toObject(); const QJsonObject body = ob.value("body").toObject();
if (event == "output") {
const QString category = body.value("category").toString(); const QString category = body.value("category").toString();
const QString output = body.value("output").toString(); const QString output = body.value("output").toString();
if (category == "stdout") if (category == "stdout")
@@ -599,10 +617,61 @@ void DapEngine::handleOutput(const QJsonDocument &data)
} }
if (event == "stopped") { if (event == "stopped") {
showMessage(event, LogDebug);
if (body.value("reason").toString() == "breakpoint") {
QString id = QString::number(body.value("hitBreakpointIds").toArray().first().toInteger());
const BreakpointParameters &params
= breakHandler()->findBreakpointByResponseId(id)->requestedParameters();
gotoLocation(Location(params.fileName, params.lineNumber));
}
if (state() == InferiorStopRequested)
notifyInferiorStopOk();
else
notifyInferiorSpontaneousStop(); notifyInferiorSpontaneousStop();
return; return;
} }
if (event == "thread") {
showMessage(event, LogDebug);
if (body.value("reason").toString() == "started" && body.value("threadId").toInt() == 1)
claimInitialBreakpoints();
return;
}
if (event == "breakpoint") {
showMessage(event, LogDebug);
QJsonObject breakpoint = body.value("breakpoint").toObject();
Breakpoint bp = breakHandler()->findBreakpointByResponseId(
QString::number(breakpoint.value("id").toInt()));
qDebug() << "breakpoint id :" << breakpoint.value("id").toInt();
if (body.value("reason").toString() == "new") {
if (breakpoint.value("verified").toBool()) {
// bp->setPending(false);
notifyBreakpointInsertOk(bp);
qDebug() << "breakpoint inserted";
} else {
notifyBreakpointInsertFailed(bp);
qDebug() << "breakpoint insertion failed";
}
return;
}
if (body.value("reason").toString() == "removed") {
if (breakpoint.value("verified").toBool()) {
notifyBreakpointRemoveOk(bp);
qDebug() << "breakpoint removed";
} else {
notifyBreakpointRemoveFailed(bp);
qDebug() << "breakpoint remove failed";
}
return;
}
return;
}
showMessage("UNKNOWN EVENT:" + event); showMessage("UNKNOWN EVENT:" + event);
return; return;
} }
@@ -686,10 +755,10 @@ void DapEngine::claimInitialBreakpoints()
{ {
BreakpointManager::claimBreakpointsForEngine(this); BreakpointManager::claimBreakpointsForEngine(this);
qDebug() << "claimInitialBreakpoints"; qDebug() << "claimInitialBreakpoints";
const Breakpoints bps = breakHandler()->breakpoints(); // const Breakpoints bps = breakHandler()->breakpoints();
for (const Breakpoint &bp : bps) // for (const Breakpoint &bp : bps)
qDebug() << "breakpoit: " << bp->fileName() << bp->lineNumber(); // qDebug() << "breakpoit: " << bp->fileName() << bp->lineNumber();
qDebug() << "claimInitialBreakpoints end"; // qDebug() << "claimInitialBreakpoints end";
// const DebuggerRunParameters &rp = runParameters(); // const DebuggerRunParameters &rp = runParameters();
// if (rp.startMode != AttachToCore) { // if (rp.startMode != AttachToCore) {

View File

@@ -92,6 +92,7 @@ private:
QByteArray m_inbuffer; QByteArray m_inbuffer;
Utils::QtcProcess m_proc; Utils::QtcProcess m_proc;
int m_nextBreakpointId = 1;
}; };
} // Debugger::Internal } // Debugger::Internal