Debugger[CDB]: Add source mapping in stack parser.

This commit is contained in:
Friedemann Kleint
2011-03-04 17:28:15 +01:00
parent 7c9dcec747
commit f6ccdfb2cd
2 changed files with 67 additions and 19 deletions

View File

@@ -89,6 +89,7 @@ Q_DECLARE_METATYPE(Debugger::Internal::MemoryAgent*)
enum { debug = 0 }; enum { debug = 0 };
enum { debugLocals = 0 }; enum { debugLocals = 0 };
enum { debugSourceMapping = 0 };
enum { debugWatches = 0 }; enum { debugWatches = 0 };
enum { debugBreakpoints = 0 }; enum { debugBreakpoints = 0 };
@@ -462,6 +463,19 @@ void CdbEngine::init()
m_extensionMessageBuffer.clear(); m_extensionMessageBuffer.clear();
m_pendingBreakpointMap.clear(); m_pendingBreakpointMap.clear();
m_customSpecialStopData.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); ) QTC_ASSERT(m_process.state() != QProcess::Running, Utils::SynchronousProcess::stopProcess(m_process); )
} }
@@ -2359,24 +2373,46 @@ void CdbEngine::attemptBreakpointSynchronization()
postCommandSequence(CommandListBreakPoints); 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()) if (it != m_normalizedFileCache.constEnd())
return it.value(); return it.value();
const QString winF = QDir::toNativeSeparators(f); if (debugSourceMapping)
#ifdef Q_OS_WIN qDebug(">sourceMapNormalizeFileNameFromDebugger %s", qPrintable(f));
QString normalized = winNormalizeFileName(winF); // Do we have source path mappings? ->Apply.
#else QString fileName = QDir::toNativeSeparators(f);
QString normalized = winF; if (!m_sourcePathMappings.isEmpty()) {
#endif foreach (const SourcePathMapping &m, m_sourcePathMappings) {
if (normalized.isEmpty()) { // At least upper case drive letter if (fileName.startsWith(m.first, Qt::CaseInsensitive)) {
normalized = winF; fileName.replace(0, m.first.size(), m.second);
if (normalized.size() > 2 && normalized.at(1) == QLatin1Char(':')) break;
normalized[0] = normalized.at(0).toUpper(); }
}
} }
m_normalizedFileCache.insert(f, normalized); // Up/lower case normalization according to Windows.
return normalized; #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 // Parse frame from GDBMI. Duplicate of the gdb code, but that
@@ -2394,7 +2430,7 @@ static StackFrames parseFrames(const GdbMi &gdbmi)
if (fullName.isValid()) { if (fullName.isValid()) {
frame.file = QFile::decodeName(fullName.data()); frame.file = QFile::decodeName(fullName.data());
frame.line = frameMi.findChild("line").data().toInt(); 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.function = QLatin1String(frameMi.findChild("func").data());
frame.from = QLatin1String(frameMi.findChild("from").data()); frame.from = QLatin1String(frameMi.findChild("from").data());
@@ -2422,7 +2458,9 @@ unsigned CdbEngine::parseStackTrace(const GdbMi &data, bool sourceStepInto)
return ParseStackStepInto; return ParseStackStepInto;
} }
if (hasFile) { 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) if (current == -1 && frames[i].usable)
current = i; current = i;
} }

View File

@@ -42,6 +42,8 @@
#include <QtCore/QVariantList> #include <QtCore/QVariantList>
#include <QtCore/QMap> #include <QtCore/QMap>
#include <QtCore/QTime> #include <QtCore/QTime>
#include <QtCore/QPair>
#include <QtCore/QList>
namespace Utils { namespace Utils {
class ConsoleProcess; class ConsoleProcess;
@@ -164,6 +166,14 @@ private slots:
private: private:
typedef QHash<BreakpointId, BreakpointResponse> PendingBreakPointMap; 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 enum SpecialStopMode
{ {
@@ -218,8 +228,7 @@ private:
void handleWidgetAt(const CdbExtensionCommandPtr &); void handleWidgetAt(const CdbExtensionCommandPtr &);
void handleBreakPoints(const CdbExtensionCommandPtr &); void handleBreakPoints(const CdbExtensionCommandPtr &);
void handleBreakPoints(const GdbMi &value); void handleBreakPoints(const GdbMi &value);
NormalizedSourceFileName sourceMapNormalizeFileNameFromDebugger(const QString &f);
QString normalizeFileName(const QString &f);
void updateLocalVariable(const QByteArray &iname); void updateLocalVariable(const QByteArray &iname);
void updateLocals(bool forNewStackFrame = false); void updateLocals(bool forNewStackFrame = false);
int elapsedLogTime() const; int elapsedLogTime() const;
@@ -243,7 +252,7 @@ private:
QList<CdbBuiltinCommandPtr> m_builtinCommandQueue; QList<CdbBuiltinCommandPtr> m_builtinCommandQueue;
int m_currentBuiltinCommandIndex; //!< Current command whose output is recorded. int m_currentBuiltinCommandIndex; //!< Current command whose output is recorded.
QList<CdbExtensionCommandPtr> m_extensionCommandQueue; QList<CdbExtensionCommandPtr> m_extensionCommandQueue;
QMap<QString, QString> m_normalizedFileCache; QMap<QString, NormalizedSourceFileName> m_normalizedFileCache;
const QByteArray m_extensionCommandPrefixBA; //!< Library name used as prefix const QByteArray m_extensionCommandPrefixBA; //!< Library name used as prefix
bool m_operateByInstructionPending; //!< Creator operate by instruction action changed. bool m_operateByInstructionPending; //!< Creator operate by instruction action changed.
bool m_operateByInstruction; bool m_operateByInstruction;
@@ -259,6 +268,7 @@ private:
QHash<QString, QString> m_fileNameModuleHash; QHash<QString, QString> m_fileNameModuleHash;
bool m_ignoreCdbOutput; bool m_ignoreCdbOutput;
QVariantList m_customSpecialStopData; QVariantList m_customSpecialStopData;
QList<SourcePathMapping> m_sourcePathMappings;
}; };
} // namespace Internal } // namespace Internal