diff --git a/src/plugins/debugger/cdb/cdbengine.cpp b/src/plugins/debugger/cdb/cdbengine.cpp index d8210f0ee88a6a942ff0a8bebc84d34359acbde9..1606f5c098611b2b9b6f58787a7090f31b6e3728 100644 --- a/src/plugins/debugger/cdb/cdbengine.cpp +++ b/src/plugins/debugger/cdb/cdbengine.cpp @@ -1147,7 +1147,7 @@ void CdbEngine::executeRunToLine(const ContextData &data) bp.fileName = data.fileName; bp.lineNumber = data.lineNumber; } - postCommand(cdbAddBreakpointCommand(bp, BreakpointId(-1), true), 0); + postCommand(cdbAddBreakpointCommand(bp, m_sourcePathMappings, BreakpointId(-1), true), 0); continueInferior(); } @@ -1157,7 +1157,7 @@ void CdbEngine::executeRunToFunction(const QString &functionName) BreakpointParameters bp(BreakpointByFunction); bp.functionName = functionName; - postCommand(cdbAddBreakpointCommand(bp, BreakpointId(-1), true), 0); + postCommand(cdbAddBreakpointCommand(bp, m_sourcePathMappings, BreakpointId(-1), true), 0); continueInferior(); } @@ -2329,7 +2329,7 @@ void CdbEngine::attemptBreakpointSynchronization() } switch (handler->state(id)) { case BreakpointInsertRequested: - postCommand(cdbAddBreakpointCommand(parameters, id, false), 0); + postCommand(cdbAddBreakpointCommand(parameters, m_sourcePathMappings, id, false), 0); if (!parameters.enabled) postCommand("bd " + QByteArray::number(id), 0); handler->notifyBreakpointInsertProceeding(id); @@ -2351,7 +2351,7 @@ void CdbEngine::attemptBreakpointSynchronization() // Delete and re-add, triggering update addedChanged = true; postCommand("bc " + QByteArray::number(id), 0); - postCommand(cdbAddBreakpointCommand(parameters, id, false), 0); + postCommand(cdbAddBreakpointCommand(parameters, m_sourcePathMappings, id, false), 0); m_pendingBreakpointMap.insert(id, response); } handler->notifyBreakpointChangeOk(id); @@ -2384,15 +2384,8 @@ CdbEngine::NormalizedSourceFileName CdbEngine::sourceMapNormalizeFileNameFromDeb if (debugSourceMapping) qDebug(">sourceMapNormalizeFileNameFromDebugger %s", qPrintable(f)); // Do we have source path mappings? ->Apply. - QString fileName = QDir::toNativeSeparators(f); - if (!m_sourcePathMappings.isEmpty()) { - foreach (const SourcePathMapping &m, m_sourcePathMappings) { - if (fileName.startsWith(m.first, Qt::CaseInsensitive)) { - fileName.replace(0, m.first.size(), m.second); - break; - } - } - } + const QString fileName = cdbSourcePathMapping(QDir::toNativeSeparators(f), m_sourcePathMappings, + DebuggerToSource); // Up/lower case normalization according to Windows. #ifdef Q_OS_WIN QString normalized = winNormalizeFileName(fileName); diff --git a/src/plugins/debugger/cdb/cdbparsehelpers.cpp b/src/plugins/debugger/cdb/cdbparsehelpers.cpp index 28d9c88d1bd4e4e8332499accc4cfa18c2dccda4..94776e3b39a6fbceb3f8bdab37fdc94260317534 100644 --- a/src/plugins/debugger/cdb/cdbparsehelpers.cpp +++ b/src/plugins/debugger/cdb/cdbparsehelpers.cpp @@ -53,8 +53,50 @@ namespace Debugger { namespace Internal { -// Convert breakpoint in CDB syntax. +// Perform mapping on parts of the source tree as reported by/passed to debugger +// in case the user has specified such mappings in the global settings. +// That is, when debugging an executable built from 'X:\buildsrv\foo.cpp' and using a local +// source tree under 'c:\src', the user would specify a mapping 'X:\buildsrv'->'c:\src' +// and file names passed to breakpoints and reported stack traces can be converted. +QString cdbSourcePathMapping(QString fileName, + const QList<QPair<QString, QString> > &sourcePathMapping, + SourcePathMode mode) +{ + typedef QPair<QString, QString> SourcePathMapping; + + if (fileName.isEmpty() || sourcePathMapping.isEmpty()) + return fileName; + foreach (const SourcePathMapping &m, sourcePathMapping) { + const QString &source = mode == DebuggerToSource ? m.first : m.second; + const int sourceSize = source.size(); + // Map parts of the path and ensure a slash follows. + if (fileName.size() > sourceSize && fileName.startsWith(source, Qt::CaseInsensitive)) { + const QChar next = fileName.at(sourceSize); + if (next == QLatin1Char('\\') || next == QLatin1Char('/')) { + const QString &target = mode == DebuggerToSource ? m.second: m.first; + fileName.replace(0, sourceSize, target); + return fileName; + } + } + } + return fileName; +} + +// Determine file name to be used for breakpoints. Convert to native and, unless short path +// is set, perform reverse lookup in the source path mappings. +static inline QString cdbBreakPointFileName(const BreakpointParameters &bp, + const QList<QPair<QString, QString> > &sourcePathMapping) +{ + if (bp.fileName.isEmpty()) + return bp.fileName; + if (bp.pathUsage == BreakpointUseShortPath) + return QFileInfo(bp.fileName).fileName(); + return cdbSourcePathMapping(QDir::toNativeSeparators(bp.fileName), sourcePathMapping, SourceToDebugger); +} + +// Convert breakpoint in CDB syntax. (applying source path mappings using native paths). QByteArray cdbAddBreakpointCommand(const BreakpointParameters &bpIn, + const QList<QPair<QString, QString> > &sourcePathMapping, BreakpointId id /* = BreakpointId(-1) */, bool oneshot) { @@ -97,12 +139,7 @@ QByteArray cdbAddBreakpointCommand(const BreakpointParameters &bpIn, str << '`'; if (!bp.module.isEmpty()) str << bp.module << '!'; - if (bp.pathUsage == BreakpointUseShortPath) { - str << QFileInfo(bp.fileName).fileName(); - } else { - str << QDir::toNativeSeparators(bp.fileName); - } - str << ':' << bp.lineNumber << '`'; + str << cdbBreakPointFileName(bp, sourcePathMapping) << ':' << bp.lineNumber << '`'; break; case Watchpoint: str << "rw 1 " << hex << hexPrefixOn << bp.address << hexPrefixOff << dec; diff --git a/src/plugins/debugger/cdb/cdbparsehelpers.h b/src/plugins/debugger/cdb/cdbparsehelpers.h index 0f8f8035e514b3559aea65ceaa1710eab2558e8f..65f9362706748272ffce88bfa8b895dca3e8c1ad 100644 --- a/src/plugins/debugger/cdb/cdbparsehelpers.h +++ b/src/plugins/debugger/cdb/cdbparsehelpers.h @@ -39,6 +39,7 @@ #include <QtCore/QtGlobal> #include <QtCore/QList> #include <QtCore/QVector> +#include <QtCore/QPair> #include <QtCore/QByteArray> QT_BEGIN_NAMESPACE @@ -54,8 +55,17 @@ struct ThreadData; class Register; class GdbMi; -// Convert breakpoint in CDB syntax. -QByteArray cdbAddBreakpointCommand(const BreakpointParameters &d, BreakpointId id = BreakpointId(-1), bool oneshot = false); +// Perform mapping on parts of the source tree as reported by/passed to debugger +// in case the user has specified such mappings in the global settings. +enum SourcePathMode { DebuggerToSource, SourceToDebugger }; +QString cdbSourcePathMapping(QString fileName, + const QList<QPair<QString, QString> > &sourcePathMapping, + SourcePathMode mode); + +// Convert breakpoint in CDB syntax (applying source path mappings using native paths). +QByteArray cdbAddBreakpointCommand(const BreakpointParameters &d, + const QList<QPair<QString, QString> > &sourcePathMapping, + BreakpointId id = BreakpointId(-1), bool oneshot = 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).