CDB: Only use codemodel breakpoint correction for old cdbs.

Since version 6.2 cdb supports setting breakpoints on non
codelines and automatically set it to the next available line.

Change-Id: I27facf4f2463bad76a20ef0abb5a5412471c296f
Reviewed-by: Friedemann Kleint <Friedemann.Kleint@digia.com>
This commit is contained in:
David Schulz
2014-05-14 10:20:03 +02:00
parent fe238305e5
commit 84790f9aef
8 changed files with 63 additions and 4 deletions

View File

@@ -136,3 +136,14 @@ std::string moduleNameByOffset(CIDebugSymbols *symbols, ULONG64 offset)
return std::string();
return std::string(buf);
}
std::string sourceFileNameByOffset(CIDebugSymbols *symbols, ULONG64 offset, PULONG lineNumber)
{
enum { BufSize = 512 };
char buf[BufSize];
buf[0] = '\0';
HRESULT hr = symbols->GetLineByOffset(offset, lineNumber, buf, BufSize, NULL, NULL);
if (FAILED(hr))
return std::string();
return std::string(buf);
}

View File

@@ -71,6 +71,7 @@ ULONG currentThreadId(CIDebugClient *client);
ULONG currentProcessId(IDebugSystemObjects *sysObjects);
ULONG currentProcessId(CIDebugClient *client);
std::string moduleNameByOffset(CIDebugSymbols *symbols, ULONG64 offset);
std::string sourceFileNameByOffset(CIDebugSymbols *symbols, ULONG64 offset, PULONG lineNumber);
#ifdef QTC_TRACE
# define QTC_TRACE_IN dprintf(">%s\n", __FUNCTION__);

View File

@@ -742,6 +742,14 @@ static bool gdbmiFormatBreakpoint(std::ostream &str,
const std::string module = moduleNameByOffset(symbols, memoryRange.first);
if (!module.empty())
str << ",module=\"" << module << '"';
ULONG lineNumber = 0;
std::string srcFile = sourceFileNameByOffset(symbols, memoryRange.first, &lineNumber);
if (!srcFile.empty()) {
// replace all backslashes with slashes
replace(srcFile, '\\', '/');
str << ",srcfile=\"" << srcFile << '"';
str << ",srcline=\"" << lineNumber << '"';
}
} // symbols
// Report the memory of watchpoints for comparing bitfields
if (dataSpaces && memoryRange.second > 0) {
@@ -755,7 +763,7 @@ static bool gdbmiFormatBreakpoint(std::ostream &str,
// Expression
if (verbose > 1) {
char buf[BufSize];
if (SUCCEEDED(bp->GetOffsetExpression(buf, BUFSIZ, 0)))
if (SUCCEEDED(bp->GetOffsetExpression(buf, BufSize, 0)))
str << ",expression=\"" << gdbmiStringFormat(buf) << '"';
}
return true;

View File

@@ -102,6 +102,14 @@ void replace(std::wstring &s, wchar_t before, wchar_t after)
s[i] = after;
}
void replace(std::string &s, char before, char after)
{
const std::string::size_type size = s.size();
for (std::string::size_type i = 0; i < size; ++i)
if (s.at(i) == before)
s[i] = after;
}
bool endsWith(const std::string &haystack, const char *needle)
{
const size_t needleLen = strlen(needle);

View File

@@ -134,6 +134,7 @@ bool integerFromWString(const std::wstring &s, Integer *v)
}
void replace(std::wstring &s, wchar_t before, wchar_t after);
void replace(std::string &s, char before, char after);
// Stream a string onto a char stream doing backslash & octal escaping
// suitable for GDBMI usable as 'str << gdbmiStringFormat(wstring)'

View File

@@ -375,6 +375,7 @@ void CdbEngine::init()
m_sourceStepInto = false;
m_watchPointX = m_watchPointY = 0;
m_ignoreCdbOutput = false;
m_autoBreakPointCorrection = false;
m_watchInameToName.clear();
m_wow64State = wow64Uninitialized;
@@ -733,6 +734,7 @@ bool CdbEngine::launchCDB(const DebuggerStartParameters &sp, QString *errorMessa
showMessage(msg, LogMisc);
m_outputBuffer.clear();
m_autoBreakPointCorrection = false;
const QStringList environment = sp.environment.size() == 0 ?
QProcessEnvironment::systemEnvironment().toStringList() :
sp.environment.toStringList();
@@ -2609,7 +2611,24 @@ void CdbEngine::parseOutputLine(QByteArray line)
qDebug("### Gathering output for '%s' token %d", currentCommand->command.constData(), currentCommand->token);
return;
}
const char versionString[] = "Microsoft (R) Windows Debugger Version";
if (line.startsWith(versionString)) {
QRegExp versionRegEx(QLatin1String("(\\d+)\\.(\\d+)\\.\\d+\\.\\d+"));
if (versionRegEx.indexIn(QLatin1String(line)) > -1) {
bool ok = true;
int major = versionRegEx.cap(1).toInt(&ok);
int minor = versionRegEx.cap(2).toInt(&ok);
if (ok) {
// for some incomprehensible reasons Microsoft cdb version 6.2 is newer than 6.12
m_autoBreakPointCorrection = major > 6 || (major == 6 && minor >= 2 && minor < 10);
showMessage(QString::fromLocal8Bit(line), LogMisc);
showMessage(QString::fromLatin1("Using ")
+ m_autoBreakPointCorrection ? QLatin1String("CDB ")
: QLatin1String("codemodel ")
+ QString::fromLatin1("based breakpoint correction."), LogMisc);
}
}
}
showMessage(QString::fromLocal8Bit(line), LogMisc);
}
@@ -2814,8 +2833,9 @@ void CdbEngine::attemptBreakpointSynchronization()
}
switch (handler->state(id)) {
case BreakpointInsertRequested:
if (parameters.type == BreakpointByFileAndLine
&& debuggerCore()->boolSetting(CdbBreakPointCorrection)) {
if (!m_autoBreakPointCorrection
&& parameters.type == BreakpointByFileAndLine
&& debuggerCore()->boolSetting(CdbBreakPointCorrection)) {
if (lineCorrection.isNull())
lineCorrection.reset(new BreakpointCorrectionContext(debuggerCore()->cppCodeModelSnapshot(),
CppTools::CppModelManagerInterface::instance()->workingCopy()));
@@ -3210,6 +3230,8 @@ void CdbEngine::handleBreakPoints(const GdbMi &value)
currentResponse.module = reportedResponse.module;
currentResponse.pending = reportedResponse.pending;
currentResponse.enabled = reportedResponse.enabled;
currentResponse.fileName = reportedResponse.fileName;
currentResponse.lineNumber = reportedResponse.lineNumber;
formatCdbBreakPointResponse(mid, currentResponse, str);
if (debugBreakpoints)
qDebug(" Setting for %d: %s\n", currentResponse.id.majorPart(),

View File

@@ -286,6 +286,7 @@ private:
int m_watchPointX;
int m_watchPointY;
PendingBreakPointMap m_pendingBreakpointMap;
bool m_autoBreakPointCorrection;
QHash<QString, QString> m_fileNameModuleHash;
QMultiHash<QString, quint64> m_symbolAddressCache;
QHash<QByteArray, QString> m_watchInameToName;

View File

@@ -300,6 +300,13 @@ void parseBreakPoint(const GdbMi &gdbmi, BreakpointResponse *r,
const GdbMi moduleG = gdbmi["module"];
if (moduleG.isValid())
r->module = QString::fromLocal8Bit(moduleG.data());
const GdbMi sourceFileName = gdbmi["srcfile"];
if (sourceFileName.isValid()) {
r->fileName = QString::fromLocal8Bit(sourceFileName.data());
const GdbMi lineNumber = gdbmi["srcline"];
if (lineNumber.isValid())
r->lineNumber = lineNumber.data().toULongLong(0, 0);
}
if (expression) {
const GdbMi expressionG = gdbmi["expression"];
if (expressionG.isValid())