CDB: Handle "ambiguous symbol" messages on breakpoint inserts.

These messages usually appear when there is a lambda at the position
the breakpoint is about to be inserted.

Task-number: QTCREATORBUG-12178
Task-number: QTCREATORBUG-12016
Change-Id: I20f7b0e900147030bfd08206fab869ac22810825
Reviewed-by: Friedemann Kleint <Friedemann.Kleint@digia.com>
Reviewed-by: hjk <hjk121@nokiamail.com>
This commit is contained in:
David Schulz
2014-05-14 10:38:16 +02:00
parent 84790f9aef
commit 04fdbe3d01
4 changed files with 188 additions and 45 deletions

View File

@@ -384,6 +384,8 @@ void CdbEngine::init()
m_extensionCommandQueue.clear(); m_extensionCommandQueue.clear();
m_extensionMessageBuffer.clear(); m_extensionMessageBuffer.clear();
m_pendingBreakpointMap.clear(); m_pendingBreakpointMap.clear();
m_insertSubBreakpointMap.clear();
m_pendingSubBreakpointMap.clear();
m_customSpecialStopData.clear(); m_customSpecialStopData.clear();
m_symbolAddressCache.clear(); m_symbolAddressCache.clear();
m_coreStopReason.reset(); m_coreStopReason.reset();
@@ -780,8 +782,9 @@ void CdbEngine::setupInferior()
attemptBreakpointSynchronization(); attemptBreakpointSynchronization();
if (sp.breakOnMain) { if (sp.breakOnMain) {
const BreakpointParameters bp(BreakpointAtMain); const BreakpointParameters bp(BreakpointAtMain);
postCommand(cdbAddBreakpointCommand(bp, m_sourcePathMappings, postBuiltinCommand(cdbAddBreakpointCommand(bp, m_sourcePathMappings,
BreakpointModelId(quint16(-1)), true), 0); BreakpointModelId(quint16(-1)), true), 0,
&CdbEngine::handleBreakInsert);
} }
postCommand("sxn 0x4000001f", 0); // Do not break on WowX86 exceptions. postCommand("sxn 0x4000001f", 0); // Do not break on WowX86 exceptions.
postCommand("sxn ibp", 0); // Do not break on initial breakpoints. postCommand("sxn ibp", 0); // Do not break on initial breakpoints.
@@ -838,18 +841,26 @@ void CdbEngine::runEngine()
const QByteArray module = msvcRunTime(startParameters().toolChainAbi.osFlavor()); const QByteArray module = msvcRunTime(startParameters().toolChainAbi.osFlavor());
const QByteArray debugModule = module + 'D'; const QByteArray debugModule = module + 'D';
const QByteArray wideFunc = QByteArray(CdbOptionsPage::crtDbgReport).append('W'); const QByteArray wideFunc = QByteArray(CdbOptionsPage::crtDbgReport).append('W');
postCommand(breakAtFunctionCommand(CdbOptionsPage::crtDbgReport, module), 0); postBuiltinCommand(breakAtFunctionCommand(CdbOptionsPage::crtDbgReport, module), 0,
postCommand(breakAtFunctionCommand(wideFunc, module), 0); &CdbEngine::handleBreakInsert);
postCommand(breakAtFunctionCommand(CdbOptionsPage::crtDbgReport, debugModule), 0); postBuiltinCommand(breakAtFunctionCommand(wideFunc, module), 0,
postCommand(breakAtFunctionCommand(wideFunc, debugModule), 0); &CdbEngine::handleBreakInsert);
postBuiltinCommand(breakAtFunctionCommand(CdbOptionsPage::crtDbgReport, debugModule), 0,
&CdbEngine::handleBreakInsert);
postBuiltinCommand(breakAtFunctionCommand(wideFunc, debugModule), 0,
&CdbEngine::handleBreakInsert);
} }
if (debuggerCore()->boolSetting(BreakOnWarning)) { if (debuggerCore()->boolSetting(BreakOnWarning)) {
postCommand("bm /( QtCored4!qWarning", 0); // 'bm': All overloads. postBuiltinCommand("bm /( QtCored4!qWarning", 0,
postCommand("bm /( Qt5Cored!QMessageLogger::warning", 0); &CdbEngine::handleBreakInsert); // 'bm': All overloads.
postBuiltinCommand("bm /( Qt5Cored!QMessageLogger::warning", 0,
&CdbEngine::handleBreakInsert);
} }
if (debuggerCore()->boolSetting(BreakOnFatal)) { if (debuggerCore()->boolSetting(BreakOnFatal)) {
postCommand("bm /( QtCored4!qFatal", 0); // 'bm': All overloads. postBuiltinCommand("bm /( QtCored4!qFatal", 0,
postCommand("bm /( Qt5Cored!QMessageLogger::fatal", 0); &CdbEngine::handleBreakInsert); // 'bm': All overloads.
postBuiltinCommand("bm /( Qt5Cored!QMessageLogger::fatal", 0,
&CdbEngine::handleBreakInsert);
} }
if (startParameters().startMode == AttachCore) { if (startParameters().startMode == AttachCore) {
QTC_ASSERT(!m_coreStopReason.isNull(), return; ); QTC_ASSERT(!m_coreStopReason.isNull(), return; );
@@ -1218,7 +1229,8 @@ void CdbEngine::executeRunToLine(const ContextData &data)
bp.fileName = data.fileName; bp.fileName = data.fileName;
bp.lineNumber = data.lineNumber; bp.lineNumber = data.lineNumber;
} }
postCommand(cdbAddBreakpointCommand(bp, m_sourcePathMappings, BreakpointModelId(), true), 0); postBuiltinCommand(cdbAddBreakpointCommand(bp, m_sourcePathMappings, BreakpointModelId(), true),
0, &CdbEngine::handleBreakInsert);
continueInferior(); continueInferior();
} }
@@ -1228,7 +1240,8 @@ void CdbEngine::executeRunToFunction(const QString &functionName)
BreakpointParameters bp(BreakpointByFunction); BreakpointParameters bp(BreakpointByFunction);
bp.functionName = functionName; bp.functionName = functionName;
postCommand(cdbAddBreakpointCommand(bp, m_sourcePathMappings, BreakpointModelId(), true), 0); postBuiltinCommand(cdbAddBreakpointCommand(bp, m_sourcePathMappings, BreakpointModelId(), true),
0, &CdbEngine::handleBreakInsert);
continueInferior(); continueInferior();
} }
@@ -2272,7 +2285,7 @@ void CdbEngine::processStop(const GdbMi &stopReason, bool conditionalBreakPointT
showMessage(QString::fromLatin1(stopReason["threaderror"].data()), LogError); showMessage(QString::fromLatin1(stopReason["threaderror"].data()), LogError);
} }
// Fire off remaining commands asynchronously // Fire off remaining commands asynchronously
if (!m_pendingBreakpointMap.isEmpty()) if (!m_pendingBreakpointMap.isEmpty() && !m_pendingSubBreakpointMap.isEmpty())
postCommandSequence(CommandListBreakPoints); postCommandSequence(CommandListBreakPoints);
if (debuggerCore()->isDockVisible(QLatin1String(DOCKWIDGET_REGISTER))) if (debuggerCore()->isDockVisible(QLatin1String(DOCKWIDGET_REGISTER)))
postCommandSequence(CommandListRegisters); postCommandSequence(CommandListRegisters);
@@ -2285,6 +2298,69 @@ void CdbEngine::processStop(const GdbMi &stopReason, bool conditionalBreakPointT
showStoppedByExceptionMessageBox(exceptionBoxMessage); showStoppedByExceptionMessageBox(exceptionBoxMessage);
} }
void CdbEngine::handleBreakInsert(const CdbBuiltinCommandPtr &cmd)
{
const QList<QByteArray> &reply = cmd->reply;
if (reply.isEmpty())
return;
foreach (const QByteArray &line, reply)
showMessage(QString::fromLocal8Bit(line));
if (!reply.last().startsWith("Ambiguous symbol error") &&
(reply.length() < 2 || !reply.at(reply.length() - 2).startsWith("Ambiguous symbol error"))) {
return;
}
// *** WARNING: Unable to verify checksum for C:\dev\builds\qt5\qtbase\lib\Qt5Cored.dll
// *** WARNING: Unable to verify checksum for untitled2.exe", "Matched: untitled2!main+0xc (000007f6`a103241c)
// Matched: untitled123!main+0x1b6 (000007f6`be2f25c6)
// Matched: untitled123!<lambda_4956dbaf7bce78acbc6759af75f3884a>::operator() (000007f6`be2f26b0)
// Matched: untitled123!<lambda_4956dbaf7bce78acbc6759af75f3884a>::<helper_func_cdecl> (000007f6`be2f2730)
// Matched: untitled123!<lambda_4956dbaf7bce78acbc6759af75f3884a>::operator QString (__cdecl*)(void) (000007f6`be2f27b0)
// Matched: untitled123!<lambda_4956dbaf7bce78acbc6759af75f3884a>::<helper_func_vectorcall> (000007f6`be2f27d0)
// Matched: untitled123!<lambda_4956dbaf7bce78acbc6759af75f3884a>::operator QString (__vectorcall*)(void) (000007f6`be2f2850)
// Ambiguous symbol error at '`untitled2!C:\dev\src\tmp\untitled2\main.cpp:18`'
// ^ Extra character error in 'bu1004 `untitled2!C:\dev\src\tmp\untitled2\main.cpp:18`'
// extract break point model id from command
QRegExp numberRegEx(QLatin1String("\\d"));
const int numberStart = numberRegEx.indexIn(QLatin1String(cmd->command));
if (numberStart == -1)
return;
const int numberEnd = cmd->command.indexOf(' ', numberStart);
bool ok = true;
const int cdbBreakPointId = cmd->command.mid(numberStart, numberEnd - numberStart).toInt(&ok);
if (!ok)
return;
const BreakpointModelId &originalId = cdbIdToBreakpointModelId(cdbBreakPointId);
// add break point for every match
const QList<QByteArray>::const_iterator &end = reply.cend();
int subBreakPointID = 0;
for (QList<QByteArray>::const_iterator line = reply.cbegin(); line != end; ++line) {
if (!line->startsWith("Matched: "))
continue;
const int addressStartPos = line->lastIndexOf('(') + 1;
const int addressEndPos = line->indexOf(')', addressStartPos);
if (addressStartPos == 0 || addressEndPos == -1)
continue;
QByteArray addressString = line->mid(addressStartPos, addressEndPos - addressStartPos);
addressString.replace("`", "");
bool ok = true;
quint64 address = addressString.toULongLong(&ok, 16);
if (!ok)
continue;
BreakpointModelId id(originalId.majorPart(), ++subBreakPointID);
BreakpointResponse res = breakHandler()->response(originalId);
res.type = BreakpointByAddress;
res.address = address;
m_insertSubBreakpointMap.insert(id, res);
}
if (subBreakPointID == 0)
return;
attemptBreakpointSynchronization();
}
void CdbEngine::handleCheckWow64(const CdbBuiltinCommandPtr &cmd) void CdbEngine::handleCheckWow64(const CdbBuiltinCommandPtr &cmd)
{ {
// Using the lm (list modules) command to check if there is a 32 bit subsystem in this debuggee. // Using the lm (list modules) command to check if there is a 32 bit subsystem in this debuggee.
@@ -2781,25 +2857,27 @@ void CdbEngine::attemptBreakpointSynchronization()
handler->setEngine(id, this); handler->setEngine(id, this);
// Quick check: is there a need to change something? - Populate module cache // Quick check: is there a need to change something? - Populate module cache
bool changed = false; bool changed = !m_insertSubBreakpointMap.isEmpty();
const BreakpointModelIds ids = handler->engineBreakpointIds(this); const BreakpointModelIds ids = handler->engineBreakpointIds(this);
foreach (BreakpointModelId id, ids) { if (!changed) {
switch (handler->state(id)) { foreach (BreakpointModelId id, ids) {
case BreakpointInsertRequested: switch (handler->state(id)) {
case BreakpointRemoveRequested: case BreakpointInsertRequested:
case BreakpointChangeRequested: case BreakpointRemoveRequested:
changed = true; case BreakpointChangeRequested:
break; changed = true;
case BreakpointInserted: { break;
// Collect the new modules matching the files. case BreakpointInserted: {
// In the future, that information should be obtained from the build system. // Collect the new modules matching the files.
const BreakpointParameters &data = handler->breakpointData(id); // In the future, that information should be obtained from the build system.
if (data.type == BreakpointByFileAndLine && !data.module.isEmpty()) const BreakpointParameters &data = handler->breakpointData(id);
m_fileNameModuleHash.insert(data.fileName, data.module); if (data.type == BreakpointByFileAndLine && !data.module.isEmpty())
} m_fileNameModuleHash.insert(data.fileName, data.module);
break; }
default: break;
break; default:
break;
}
} }
} }
@@ -2840,9 +2918,13 @@ void CdbEngine::attemptBreakpointSynchronization()
lineCorrection.reset(new BreakpointCorrectionContext(debuggerCore()->cppCodeModelSnapshot(), lineCorrection.reset(new BreakpointCorrectionContext(debuggerCore()->cppCodeModelSnapshot(),
CppTools::CppModelManagerInterface::instance()->workingCopy())); CppTools::CppModelManagerInterface::instance()->workingCopy()));
response.lineNumber = lineCorrection->fixLineNumber(parameters.fileName, parameters.lineNumber); response.lineNumber = lineCorrection->fixLineNumber(parameters.fileName, parameters.lineNumber);
postCommand(cdbAddBreakpointCommand(response, m_sourcePathMappings, id, false), 0); postBuiltinCommand(
cdbAddBreakpointCommand(response, m_sourcePathMappings, id, false), 0,
&CdbEngine::handleBreakInsert);
} else { } else {
postCommand(cdbAddBreakpointCommand(parameters, m_sourcePathMappings, id, false), 0); postBuiltinCommand(
cdbAddBreakpointCommand(parameters, m_sourcePathMappings, id, false), 0,
&CdbEngine::handleBreakInsert);
} }
if (!parameters.enabled) if (!parameters.enabled)
postCommand("bd " + QByteArray::number(breakPointIdToCdbId(id)), 0); postCommand("bd " + QByteArray::number(breakPointIdToCdbId(id)), 0);
@@ -2872,14 +2954,16 @@ void CdbEngine::attemptBreakpointSynchronization()
} else { } else {
// Delete and re-add, triggering update // Delete and re-add, triggering update
addedChanged = true; addedChanged = true;
postCommand("bc " + QByteArray::number(breakPointIdToCdbId(id)), 0); postCommand(cdbClearBreakpointCommand(id), 0);
postCommand(cdbAddBreakpointCommand(parameters, m_sourcePathMappings, id, false), 0); postBuiltinCommand(
cdbAddBreakpointCommand(parameters, m_sourcePathMappings, id, false), 0,
&CdbEngine::handleBreakInsert);
m_pendingBreakpointMap.insert(id, response); m_pendingBreakpointMap.insert(id, response);
} }
handler->notifyBreakpointChangeOk(id); handler->notifyBreakpointChangeOk(id);
break; break;
case BreakpointRemoveRequested: case BreakpointRemoveRequested:
postCommand("bc " + QByteArray::number(breakPointIdToCdbId(id)), 0); postCommand(cdbClearBreakpointCommand(id), 0);
handler->notifyBreakpointRemoveProceeding(id); handler->notifyBreakpointRemoveProceeding(id);
handler->notifyBreakpointRemoveOk(id); handler->notifyBreakpointRemoveOk(id);
m_pendingBreakpointMap.remove(id); m_pendingBreakpointMap.remove(id);
@@ -2888,6 +2972,13 @@ void CdbEngine::attemptBreakpointSynchronization()
break; break;
} }
} }
foreach (BreakpointModelId id, m_insertSubBreakpointMap.keys()) {
addedChanged = true;
const BreakpointResponse &response = m_insertSubBreakpointMap.value(id);
postCommand(cdbAddBreakpointCommand(response, m_sourcePathMappings, id, false), 0);
m_insertSubBreakpointMap.remove(id);
m_pendingSubBreakpointMap.insert(id, response);
}
// List breakpoints and send responses // List breakpoints and send responses
if (addedChanged) if (addedChanged)
postCommandSequence(CommandListBreakPoints); postCommandSequence(CommandListBreakPoints);
@@ -3222,9 +3313,14 @@ void CdbEngine::handleBreakPoints(const GdbMi &value)
continue; // Breakpoints from options, CrtDbgReport() and others. continue; // Breakpoints from options, CrtDbgReport() and others.
QTC_ASSERT(mid.isValid(), continue); QTC_ASSERT(mid.isValid(), continue);
const PendingBreakPointMap::iterator it = m_pendingBreakpointMap.find(mid); const PendingBreakPointMap::iterator it = m_pendingBreakpointMap.find(mid);
if (it != m_pendingBreakpointMap.end()) { const PendingBreakPointMap::iterator subIt = m_pendingSubBreakpointMap.find(
BreakpointModelId(reportedResponse.id.majorPart(),
reportedResponse.id.minorPart()));
if (it != m_pendingBreakpointMap.end() || subIt != m_pendingSubBreakpointMap.end()) {
// Complete the response and set on handler. // Complete the response and set on handler.
BreakpointResponse &currentResponse = it.value(); BreakpointResponse currentResponse = it != m_pendingBreakpointMap.end()
? it.value()
: subIt.value();
currentResponse.id = reportedResponse.id; currentResponse.id = reportedResponse.id;
currentResponse.address = reportedResponse.address; currentResponse.address = reportedResponse.address;
currentResponse.module = reportedResponse.module; currentResponse.module = reportedResponse.module;
@@ -3235,9 +3331,15 @@ void CdbEngine::handleBreakPoints(const GdbMi &value)
formatCdbBreakPointResponse(mid, currentResponse, str); formatCdbBreakPointResponse(mid, currentResponse, str);
if (debugBreakpoints) if (debugBreakpoints)
qDebug(" Setting for %d: %s\n", currentResponse.id.majorPart(), qDebug(" Setting for %d: %s\n", currentResponse.id.majorPart(),
qPrintable(currentResponse.toString())); qPrintable(currentResponse.toString()));
handler->setResponse(mid, currentResponse); if (it != m_pendingBreakpointMap.end()) {
m_pendingBreakpointMap.erase(it); handler->setResponse(mid, currentResponse);
m_pendingBreakpointMap.erase(it);
}
if (subIt != m_pendingSubBreakpointMap.end()) {
handler->insertSubBreakpoint(mid, currentResponse);
m_pendingSubBreakpointMap.erase(subIt);
}
} }
} // not pending reported } // not pending reported
} // foreach } // foreach

View File

@@ -224,6 +224,7 @@ private:
void handleExpression(const CdbExtensionCommandPtr &); void handleExpression(const CdbExtensionCommandPtr &);
void handleResolveSymbol(const CdbBuiltinCommandPtr &command); void handleResolveSymbol(const CdbBuiltinCommandPtr &command);
void handleResolveSymbol(const QList<quint64> &addresses, const QVariant &cookie); void handleResolveSymbol(const QList<quint64> &addresses, const QVariant &cookie);
void handleBreakInsert(const CdbBuiltinCommandPtr &cmd);
void handleCheckWow64(const CdbBuiltinCommandPtr &cmd); void handleCheckWow64(const CdbBuiltinCommandPtr &cmd);
void ensureUsing32BitStackInWow64(const CdbBuiltinCommandPtr &cmd); void ensureUsing32BitStackInWow64(const CdbBuiltinCommandPtr &cmd);
void handleSwitchWow64Stack(const CdbBuiltinCommandPtr &cmd); void handleSwitchWow64Stack(const CdbBuiltinCommandPtr &cmd);
@@ -286,6 +287,8 @@ private:
int m_watchPointX; int m_watchPointX;
int m_watchPointY; int m_watchPointY;
PendingBreakPointMap m_pendingBreakpointMap; PendingBreakPointMap m_pendingBreakpointMap;
PendingBreakPointMap m_insertSubBreakpointMap;
PendingBreakPointMap m_pendingSubBreakpointMap;
bool m_autoBreakPointCorrection; bool m_autoBreakPointCorrection;
QHash<QString, QString> m_fileNameModuleHash; QHash<QString, QString> m_fileNameModuleHash;
QMultiHash<QString, quint64> m_symbolAddressCache; QMultiHash<QString, quint64> m_symbolAddressCache;

View File

@@ -132,7 +132,7 @@ static BreakpointParameters fixWinMSVCBreakpoint(const BreakpointParameters &p)
int breakPointIdToCdbId(const BreakpointModelId &id) int breakPointIdToCdbId(const BreakpointModelId &id)
{ {
return cdbBreakPointStartId + id.majorPart(); return cdbBreakPointStartId + id.majorPart() * cdbBreakPointIdMinorPart + id.minorPart();
} }
template <class ModelId> template <class ModelId>
@@ -141,8 +141,22 @@ inline ModelId cdbIdToBreakpointId(const GdbMi &data)
if (data.isValid()) { // Might not be valid if there is not id if (data.isValid()) { // Might not be valid if there is not id
bool ok; bool ok;
const int id = data.data().toInt(&ok); const int id = data.data().toInt(&ok);
if (ok && id >= cdbBreakPointStartId) if (ok)
return ModelId(id - cdbBreakPointStartId); return cdbIdToBreakpointId<ModelId>(id);
}
return ModelId();
}
template <class ModelId>
inline ModelId cdbIdToBreakpointId(const int &id)
{
if (id >= cdbBreakPointStartId) {
int major = (id - cdbBreakPointStartId) / cdbBreakPointIdMinorPart;
int minor = id % cdbBreakPointIdMinorPart;
if (minor)
return ModelId(major, minor);
else
return ModelId(major);
} }
return ModelId(); return ModelId();
} }
@@ -152,11 +166,21 @@ BreakpointModelId cdbIdToBreakpointModelId(const GdbMi &id)
return cdbIdToBreakpointId<BreakpointModelId>(id); return cdbIdToBreakpointId<BreakpointModelId>(id);
} }
BreakpointModelId cdbIdToBreakpointModelId(int id)
{
return cdbIdToBreakpointId<BreakpointModelId>(id);
}
BreakpointResponseId cdbIdToBreakpointResponseId(const GdbMi &id) BreakpointResponseId cdbIdToBreakpointResponseId(const GdbMi &id)
{ {
return cdbIdToBreakpointId<BreakpointResponseId>(id); return cdbIdToBreakpointId<BreakpointResponseId>(id);
} }
BreakpointResponseId cdbIdToBreakpointResponseId(int id)
{
return cdbIdToBreakpointId<BreakpointResponseId>(id);
}
QByteArray cdbAddBreakpointCommand(const BreakpointParameters &bpIn, QByteArray cdbAddBreakpointCommand(const BreakpointParameters &bpIn,
const QList<QPair<QString, QString> > &sourcePathMapping, const QList<QPair<QString, QString> > &sourcePathMapping,
BreakpointModelId id /* = BreakpointId() */, BreakpointModelId id /* = BreakpointId() */,
@@ -220,6 +244,16 @@ QByteArray cdbAddBreakpointCommand(const BreakpointParameters &bpIn,
return rc; return rc;
} }
QByteArray cdbClearBreakpointCommand(const BreakpointModelId &id)
{
const int firstBreakPoint = breakPointIdToCdbId(id);
if (id.isMinor())
return "bc " + QByteArray::number(firstBreakPoint);
// If this is a major break point we also want to delete all sub break points
const int lastBreakPoint = firstBreakPoint + cdbBreakPointIdMinorPart - 1;
return "bc " + QByteArray::number(firstBreakPoint) + '-' + QByteArray::number(lastBreakPoint);
}
// Fix a CDB integer value: '00000000`0012a290' -> '12a290', '0n10' ->'10' // Fix a CDB integer value: '00000000`0012a290' -> '12a290', '0n10' ->'10'
QByteArray fixCdbIntegerValue(QByteArray t, bool stripLeadingZeros, int *basePtr /* = 0 */) QByteArray fixCdbIntegerValue(QByteArray t, bool stripLeadingZeros, int *basePtr /* = 0 */)
{ {

View File

@@ -56,16 +56,20 @@ QString cdbSourcePathMapping(QString fileName,
SourcePathMode mode); SourcePathMode mode);
// Ensure unique 'namespace' for breakpoints of the breakhandler. // Ensure unique 'namespace' for breakpoints of the breakhandler.
enum { cdbBreakPointStartId = 1000 }; enum { cdbBreakPointStartId = 100000,
cdbBreakPointIdMinorPart = 100};
int breakPointIdToCdbId(const BreakpointModelId &id); int breakPointIdToCdbId(const BreakpointModelId &id);
BreakpointModelId cdbIdToBreakpointModelId(const GdbMi &id); BreakpointModelId cdbIdToBreakpointModelId(const GdbMi &id);
BreakpointModelId cdbIdToBreakpointModelId(int id);
BreakpointResponseId cdbIdToBreakpointResponseId(const GdbMi &id); BreakpointResponseId cdbIdToBreakpointResponseId(const GdbMi &id);
BreakpointResponseId cdbIdToBreakpointResponseId(int id);
// Convert breakpoint in CDB syntax (applying source path mappings using native paths). // Convert breakpoint in CDB syntax (applying source path mappings using native paths).
QByteArray cdbAddBreakpointCommand(const BreakpointParameters &d, QByteArray cdbAddBreakpointCommand(const BreakpointParameters &d,
const QList<QPair<QString, QString> > &sourcePathMapping, const QList<QPair<QString, QString> > &sourcePathMapping,
BreakpointModelId id = BreakpointModelId(quint16(-1)), bool oneshot = false); BreakpointModelId id = BreakpointModelId(quint16(-1)), bool oneshot = false);
QByteArray cdbClearBreakpointCommand(const BreakpointModelId &id);
// Parse extension command listing breakpoints. // Parse extension command listing breakpoints.
// Note that not all fields are returned, since file, line, function are encoded // 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). // in the expression (that is in addition deleted on resolving for a bp-type breakpoint).