forked from qt-creator/qt-creator
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:
@@ -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 ¶ms = 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 ¶ms = bp->requestedParameters();
|
const BreakpointParameters ¶ms = 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 ¶ms = bp->requestedParameters();
|
const BreakpointParameters ¶ms = 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 ¶ms
|
||||||
|
= 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) {
|
||||||
|
@@ -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
|
||||||
|
Reference in New Issue
Block a user