Debugger: map reported breakpoint file locations

Fixes: QTCREATORBUG-28521
Change-Id: I8229483df7fb0c51750e19d4558e81f5320e7f33
Reviewed-by: Christian Stenger <christian.stenger@qt.io>
This commit is contained in:
David Schulz
2022-11-29 14:58:50 +01:00
parent f3ce23230e
commit 7373193584
4 changed files with 52 additions and 64 deletions

View File

@@ -2872,6 +2872,56 @@ static void formatCdbBreakPointResponse(int modelId, const QString &responseId,
str << '\n';
}
// Helper to retrieve an int child from GDBMI
static inline std::optional<int> gdbmiChildToInt(const GdbMi &parent, const char *childName)
{
const GdbMi childBA = parent[childName];
if (childBA.isValid()) {
bool ok;
const int v = childBA.data().toInt(&ok);
if (ok)
return v;
}
return std::nullopt;
}
// Helper to retrieve an bool child from GDBMI
static inline std::optional<bool> gdbmiChildToBool(const GdbMi &parent, const char *childName)
{
const GdbMi childBA = parent[childName];
return childBA.isValid() ? std::make_optional(childBA.data() == "true") : std::nullopt;
}
// Parse extension command listing breakpoints.
// Note that not all fields are returned, since file, line, function are encoded
// in the expression (that is in addition deleted on resolving for a bp-type breakpoint).
BreakpointParameters CdbEngine::parseBreakPoint(const GdbMi &gdbmi)
{
BreakpointParameters result;
result.enabled = gdbmiChildToBool(gdbmi, "enabled").value_or(result.enabled);
result.pending = gdbmiChildToBool(gdbmi, "deferred").value_or(result.pending);
const GdbMi moduleG = gdbmi["module"];
if (moduleG.isValid())
result.module = moduleG.data();
const GdbMi sourceFileName = gdbmi["srcfile"];
if (sourceFileName.isValid()) {
NormalizedSourceFileName mappedFile = sourceMapNormalizeFileNameFromDebugger(
sourceFileName.data());
result.fileName = Utils::FilePath::fromUserInput(mappedFile.fileName);
const GdbMi lineNumber = gdbmi["srcline"];
if (lineNumber.isValid())
result.lineNumber = lineNumber.data().toULongLong(nullptr, 0);
}
const GdbMi addressG = gdbmi["address"];
if (addressG.isValid())
result.address = addressG.data().toULongLong(nullptr, 0);
if (const std::optional<int> ignoreCount = gdbmiChildToInt(gdbmi, "passcount"))
result.ignoreCount = *ignoreCount - 1;
result.threadSpec = gdbmiChildToInt(gdbmi, "thread").value_or(result.threadSpec);
return result;
}
void CdbEngine::handleBreakPoints(const DebuggerResponse &response)
{
if (debugBreakpoints) {
@@ -2897,8 +2947,7 @@ void CdbEngine::handleBreakPoints(const DebuggerResponse &response)
for (const GdbMi &breakPointG : response.data) {
// Might not be valid if there is not id
const QString responseId = breakPointG["id"].data();
BreakpointParameters reportedResponse;
parseBreakPoint(breakPointG, &reportedResponse);
BreakpointParameters reportedResponse = parseBreakPoint(breakPointG);
if (debugBreakpoints)
qDebug(" Parsed %s: pending=%d %s\n", qPrintable(responseId),
reportedResponse.pending,

View File

@@ -168,6 +168,7 @@ private:
unsigned parseStackTrace(const GdbMi &data, bool sourceStepInto);
void mergeStartParametersSourcePathMap();
void checkQtSdkPdbFiles(const QString &module);
BreakpointParameters parseBreakPoint(const GdbMi &gdbmi);
const QString m_tokenPrefix;
void handleSetupFailure(const QString &errorMessage);

View File

@@ -189,64 +189,6 @@ QString cdbClearBreakpointCommand(const Breakpoint &bp)
return "bc " + QString::number(firstBreakPoint) + '-' + QString::number(lastBreakPoint);
}
// Helper to retrieve an int child from GDBMI
static inline bool gdbmiChildToInt(const GdbMi &parent, const char *childName, int *target)
{
const GdbMi childBA = parent[childName];
if (childBA.isValid()) {
bool ok;
const int v = childBA.data().toInt(&ok);
if (ok) {
*target = v;
return true;
}
}
return false;
}
// Helper to retrieve an bool child from GDBMI
static inline bool gdbmiChildToBool(const GdbMi &parent, const char *childName, bool *target)
{
const GdbMi childBA = parent[childName];
if (childBA.isValid()) {
*target = childBA.data() == "true";
return true;
}
return false;
}
// Parse extension command listing breakpoints.
// Note that not all fields are returned, since file, line, function are encoded
// in the expression (that is in addition deleted on resolving for a bp-type breakpoint).
void parseBreakPoint(const GdbMi &gdbmi, BreakpointParameters *r,
QString *expression /* = 0 */)
{
gdbmiChildToBool(gdbmi, "enabled", &(r->enabled));
gdbmiChildToBool(gdbmi, "deferred", &(r->pending));
const GdbMi moduleG = gdbmi["module"];
if (moduleG.isValid())
r->module = moduleG.data();
const GdbMi sourceFileName = gdbmi["srcfile"];
if (sourceFileName.isValid()) {
r->fileName = Utils::FilePath::fromUserInput(
Utils::FileUtils::normalizedPathName(sourceFileName.data()));
const GdbMi lineNumber = gdbmi["srcline"];
if (lineNumber.isValid())
r->lineNumber = lineNumber.data().toULongLong(nullptr, 0);
}
if (expression) {
const GdbMi expressionG = gdbmi["expression"];
if (expressionG.isValid())
*expression = expressionG.data();
}
const GdbMi addressG = gdbmi["address"];
if (addressG.isValid())
r->address = addressG.data().toULongLong(nullptr, 0);
if (gdbmiChildToInt(gdbmi, "passcount", &(r->ignoreCount)))
r->ignoreCount--;
gdbmiChildToInt(gdbmi, "thread", &(r->threadSpec));
}
QString cdbWriteMemoryCommand(quint64 addr, const QByteArray &data)
{
QString cmd;

View File

@@ -38,10 +38,6 @@ QString cdbAddBreakpointCommand(const BreakpointParameters &d,
const QList<QPair<QString, QString> > &sourcePathMapping,
const QString &responseId = QString());
QString cdbClearBreakpointCommand(const Breakpoint &bp);
// Parse extension command listing breakpoints.
// Note that not all fields are returned, since file, line, function are encoded
// in the expression (that is in addition deleted on resolving for a bp-type breakpoint).
void parseBreakPoint(const GdbMi &gdbmi, BreakpointParameters *r, QString *expression = nullptr);
// Write memory (f ...).
QString cdbWriteMemoryCommand(quint64 addr, const QByteArray &data);