forked from qt-creator/qt-creator
Debugger[CDB]: Add source mapping in stack parser.
This commit is contained in:
@@ -89,6 +89,7 @@ Q_DECLARE_METATYPE(Debugger::Internal::MemoryAgent*)
|
||||
|
||||
enum { debug = 0 };
|
||||
enum { debugLocals = 0 };
|
||||
enum { debugSourceMapping = 0 };
|
||||
enum { debugWatches = 0 };
|
||||
enum { debugBreakpoints = 0 };
|
||||
|
||||
@@ -462,6 +463,19 @@ void CdbEngine::init()
|
||||
m_extensionMessageBuffer.clear();
|
||||
m_pendingBreakpointMap.clear();
|
||||
m_customSpecialStopData.clear();
|
||||
|
||||
// Create local list of mappings in native separators
|
||||
m_sourcePathMappings.clear();
|
||||
const QSharedPointer<GlobalDebuggerOptions> globalOptions = debuggerCore()->globalDebuggerOptions();
|
||||
if (!globalOptions->sourcePathMap.isEmpty()) {
|
||||
typedef GlobalDebuggerOptions::SourcePathMap::const_iterator SourcePathMapIterator;
|
||||
m_sourcePathMappings.reserve(globalOptions->sourcePathMap.size());
|
||||
const SourcePathMapIterator cend = globalOptions->sourcePathMap.constEnd();
|
||||
for (SourcePathMapIterator it = globalOptions->sourcePathMap.constBegin(); it != cend; ++it) {
|
||||
m_sourcePathMappings.push_back(SourcePathMapping(QDir::toNativeSeparators(it.key()),
|
||||
QDir::toNativeSeparators(it.value())));
|
||||
}
|
||||
}
|
||||
QTC_ASSERT(m_process.state() != QProcess::Running, Utils::SynchronousProcess::stopProcess(m_process); )
|
||||
}
|
||||
|
||||
@@ -2359,24 +2373,46 @@ void CdbEngine::attemptBreakpointSynchronization()
|
||||
postCommandSequence(CommandListBreakPoints);
|
||||
}
|
||||
|
||||
QString CdbEngine::normalizeFileName(const QString &f)
|
||||
// Pass a file name through source mapping and normalize upper/lower case (for the editor
|
||||
// manager to correctly process it) and convert to clean path.
|
||||
CdbEngine::NormalizedSourceFileName CdbEngine::sourceMapNormalizeFileNameFromDebugger(const QString &f)
|
||||
{
|
||||
QMap<QString, QString>::const_iterator it = m_normalizedFileCache.constFind(f);
|
||||
// 1) Check cache.
|
||||
QMap<QString, NormalizedSourceFileName>::const_iterator it = m_normalizedFileCache.constFind(f);
|
||||
if (it != m_normalizedFileCache.constEnd())
|
||||
return it.value();
|
||||
const QString winF = QDir::toNativeSeparators(f);
|
||||
#ifdef Q_OS_WIN
|
||||
QString normalized = winNormalizeFileName(winF);
|
||||
#else
|
||||
QString normalized = winF;
|
||||
#endif
|
||||
if (normalized.isEmpty()) { // At least upper case drive letter
|
||||
normalized = winF;
|
||||
if (normalized.size() > 2 && normalized.at(1) == QLatin1Char(':'))
|
||||
normalized[0] = normalized.at(0).toUpper();
|
||||
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;
|
||||
}
|
||||
m_normalizedFileCache.insert(f, normalized);
|
||||
return normalized;
|
||||
}
|
||||
}
|
||||
// Up/lower case normalization according to Windows.
|
||||
#ifdef Q_OS_WIN
|
||||
QString normalized = winNormalizeFileName(fileName);
|
||||
#else
|
||||
QString normalized = fileName;
|
||||
#endif
|
||||
if (debugSourceMapping)
|
||||
qDebug(" sourceMapNormalizeFileNameFromDebugger %s->%s", qPrintable(fileName), qPrintable(normalized));
|
||||
// Check if it really exists, that is normalize worked and QFileInfo confirms it.
|
||||
const bool exists = !normalized.isEmpty() && QFileInfo(normalized).isFile();
|
||||
NormalizedSourceFileName result(QDir::cleanPath(normalized.isEmpty() ? fileName : normalized), exists);
|
||||
if (!exists) {
|
||||
// At least upper case drive letter if failed.
|
||||
if (result.fileName.size() > 2 && result.fileName.at(1) == QLatin1Char(':'))
|
||||
result.fileName[0] = result.fileName.at(0).toUpper();
|
||||
}
|
||||
m_normalizedFileCache.insert(f, result);
|
||||
if (debugSourceMapping)
|
||||
qDebug("<sourceMapNormalizeFileNameFromDebugger %s %d", qPrintable(result.fileName), result.exists);
|
||||
return result;
|
||||
}
|
||||
|
||||
// Parse frame from GDBMI. Duplicate of the gdb code, but that
|
||||
@@ -2394,7 +2430,7 @@ static StackFrames parseFrames(const GdbMi &gdbmi)
|
||||
if (fullName.isValid()) {
|
||||
frame.file = QFile::decodeName(fullName.data());
|
||||
frame.line = frameMi.findChild("line").data().toInt();
|
||||
frame.usable = QFileInfo(frame.file).isFile();
|
||||
frame.usable = false; // To be decided after source path mapping.
|
||||
}
|
||||
frame.function = QLatin1String(frameMi.findChild("func").data());
|
||||
frame.from = QLatin1String(frameMi.findChild("from").data());
|
||||
@@ -2422,7 +2458,9 @@ unsigned CdbEngine::parseStackTrace(const GdbMi &data, bool sourceStepInto)
|
||||
return ParseStackStepInto;
|
||||
}
|
||||
if (hasFile) {
|
||||
frames[i].file = QDir::cleanPath(normalizeFileName(frames.at(i).file));
|
||||
const NormalizedSourceFileName fileName = sourceMapNormalizeFileNameFromDebugger(frames.at(i).file);
|
||||
frames[i].file = fileName.fileName;
|
||||
frames[i].usable = fileName.exists;
|
||||
if (current == -1 && frames[i].usable)
|
||||
current = i;
|
||||
}
|
||||
|
@@ -42,6 +42,8 @@
|
||||
#include <QtCore/QVariantList>
|
||||
#include <QtCore/QMap>
|
||||
#include <QtCore/QTime>
|
||||
#include <QtCore/QPair>
|
||||
#include <QtCore/QList>
|
||||
|
||||
namespace Utils {
|
||||
class ConsoleProcess;
|
||||
@@ -164,6 +166,14 @@ private slots:
|
||||
|
||||
private:
|
||||
typedef QHash<BreakpointId, BreakpointResponse> PendingBreakPointMap;
|
||||
typedef QPair<QString, QString> SourcePathMapping;
|
||||
struct NormalizedSourceFileName // Struct for caching mapped/normalized source files.
|
||||
{
|
||||
NormalizedSourceFileName(const QString &fn = QString(), bool e = false) : fileName(fn), exists(e) {}
|
||||
|
||||
QString fileName;
|
||||
bool exists;
|
||||
};
|
||||
|
||||
enum SpecialStopMode
|
||||
{
|
||||
@@ -218,8 +228,7 @@ private:
|
||||
void handleWidgetAt(const CdbExtensionCommandPtr &);
|
||||
void handleBreakPoints(const CdbExtensionCommandPtr &);
|
||||
void handleBreakPoints(const GdbMi &value);
|
||||
|
||||
QString normalizeFileName(const QString &f);
|
||||
NormalizedSourceFileName sourceMapNormalizeFileNameFromDebugger(const QString &f);
|
||||
void updateLocalVariable(const QByteArray &iname);
|
||||
void updateLocals(bool forNewStackFrame = false);
|
||||
int elapsedLogTime() const;
|
||||
@@ -243,7 +252,7 @@ private:
|
||||
QList<CdbBuiltinCommandPtr> m_builtinCommandQueue;
|
||||
int m_currentBuiltinCommandIndex; //!< Current command whose output is recorded.
|
||||
QList<CdbExtensionCommandPtr> m_extensionCommandQueue;
|
||||
QMap<QString, QString> m_normalizedFileCache;
|
||||
QMap<QString, NormalizedSourceFileName> m_normalizedFileCache;
|
||||
const QByteArray m_extensionCommandPrefixBA; //!< Library name used as prefix
|
||||
bool m_operateByInstructionPending; //!< Creator operate by instruction action changed.
|
||||
bool m_operateByInstruction;
|
||||
@@ -259,6 +268,7 @@ private:
|
||||
QHash<QString, QString> m_fileNameModuleHash;
|
||||
bool m_ignoreCdbOutput;
|
||||
QVariantList m_customSpecialStopData;
|
||||
QList<SourcePathMapping> m_sourcePathMappings;
|
||||
};
|
||||
|
||||
} // namespace Internal
|
||||
|
Reference in New Issue
Block a user