From eb05d2ac0b9563312c642bf0016744b8ede9562a Mon Sep 17 00:00:00 2001 From: Friedemann Kleint <Friedemann.Kleint@nokia.com> Date: Fri, 19 Feb 2010 11:58:54 +0100 Subject: [PATCH] CDB CoreEngine: Support break by address for testing purposes. --- src/plugins/debugger/cdb/breakpoint.cpp | 65 +++++++++++++++++++------ src/plugins/debugger/cdb/breakpoint.h | 12 +++-- src/plugins/debugger/cdb/coreengine.cpp | 16 ++++++ src/plugins/debugger/cdb/coreengine.h | 2 + tests/manual/ccdb/cdbapplication.cpp | 46 +++++++++-------- tests/manual/ccdb/cdbapplication.h | 4 +- 6 files changed, 104 insertions(+), 41 deletions(-) diff --git a/src/plugins/debugger/cdb/breakpoint.cpp b/src/plugins/debugger/cdb/breakpoint.cpp index 5ce3edf2d66..4b3aba87e98 100644 --- a/src/plugins/debugger/cdb/breakpoint.cpp +++ b/src/plugins/debugger/cdb/breakpoint.cpp @@ -50,8 +50,9 @@ namespace CdbCore { static const char sourceFileQuoteC = '`'; BreakPoint::BreakPoint() : - ignoreCount(0), lineNumber(-1), + address(0), + ignoreCount(0), oneShot(false), enabled(true) { @@ -59,14 +60,18 @@ BreakPoint::BreakPoint() : int BreakPoint::compare(const BreakPoint& rhs) const { - if (ignoreCount > rhs.ignoreCount) - return 1; - if (ignoreCount < rhs.ignoreCount) - return -1; if (lineNumber > rhs.lineNumber) return 1; if (lineNumber < rhs.lineNumber) return -1; + if (address > rhs.address) + return 1; + if (address < rhs.address) + return -1; + if (ignoreCount > rhs.ignoreCount) + return 1; + if (ignoreCount < rhs.ignoreCount) + return -1; if (oneShot && !rhs.oneShot) return 1; if (!oneShot && rhs.oneShot) @@ -98,11 +103,14 @@ void BreakPoint::clearExpressionData() condition.clear(); funcName.clear(); lineNumber = -1; + address = 0; } QDebug operator<<(QDebug dbg, const BreakPoint &bp) { QDebug nsp = dbg.nospace(); + if (bp.address) + nsp << "0x" << QString::number(bp.address, 16) << ' '; if (!bp.fileName.isEmpty()) { nsp << "fileName='" << bp.fileName << ':' << bp.lineNumber << '\''; } else { @@ -124,16 +132,26 @@ QString BreakPoint::expression() const // format the breakpoint expression (file/function and condition) QString rc; QTextStream str(&rc); - if (funcName.isEmpty()) { - const QChar sourceFileQuote = QLatin1Char(sourceFileQuoteC); - str << sourceFileQuote << QDir::toNativeSeparators(fileName) << QLatin1Char(':') << lineNumber << sourceFileQuote; - } else { - str << funcName; - } - if (!condition.isEmpty()) { - const QChar doubleQuote = QLatin1Char('"'); - str << QLatin1Char(' ') << doubleQuote << condition << doubleQuote; - } + do { + if (address) { + str.setIntegerBase(16); + str << "0x" << address; + str.setIntegerBase(10); + break; + } + if (!fileName.isEmpty()) { + const QChar sourceFileQuote = QLatin1Char(sourceFileQuoteC); + str << sourceFileQuote << QDir::toNativeSeparators(fileName) << QLatin1Char(':') + << lineNumber << sourceFileQuote; + break; + } + if (!funcName.isEmpty()) { + str << funcName; + break; + } + } while (false); + if (!condition.isEmpty()) + str << " \"" << condition << '"'; return rc; } @@ -335,7 +353,22 @@ bool BreakPoint::parseExpression(const QString &expr) const QChar sourceFileQuote = QLatin1Char(sourceFileQuoteC); // Check for file or function int conditionPos = 0; - if (expr.startsWith(sourceFileQuote)) { // `c:\foo.cpp:523`[ "condition"] + if (expr.startsWith(QLatin1String("0x"))) { // Check address token + conditionPos = expr.indexOf(QLatin1Char(' ')); + QString addressS; + if (conditionPos != -1) { + addressS = expr.mid(2, conditionPos - 2); + conditionPos++; + } else { + addressS = expr.mid(2); + conditionPos = expr.size(); + } + addressS.remove(QLatin1Char('\'')); // 64bit separator + bool ok; + address = addressS.toULongLong(&ok, 16); + if (!ok) + return false; + } else if (expr.startsWith(sourceFileQuote)) { // `c:\foo.cpp:523`[ "condition"] // Do not fall for the drive letter colon here const int colonPos = expr.indexOf(QLatin1Char(':'), 3); if (colonPos == -1) diff --git a/src/plugins/debugger/cdb/breakpoint.h b/src/plugins/debugger/cdb/breakpoint.h index 61fb02accd5..1d8eb050fcc 100644 --- a/src/plugins/debugger/cdb/breakpoint.h +++ b/src/plugins/debugger/cdb/breakpoint.h @@ -42,7 +42,10 @@ QT_END_NAMESPACE namespace CdbCore { /* CDB Break point data structure with utilities to - * apply to engine and to retrieve them from the engine and comparison. */ + * apply to engine and to retrieve them from the engine and comparison. + * Can stop on 'sourcefile:line', function or address. + * When/How many times it triggers can be influenced by + * condition/ignorecount and 'oneshot'-flag. */ struct BreakPoint { @@ -79,10 +82,12 @@ struct BreakPoint static void clearNormalizeFileNameCache(); QString fileName; // short name of source file - QString condition; // condition associated with breakpoint - unsigned long ignoreCount; // ignore count associated with breakpoint int lineNumber; // line in source file QString funcName; // name of containing function + quint64 address; + + QString condition; // condition associated with breakpoint + unsigned long ignoreCount; // ignore count associated with breakpoint bool oneShot; bool enabled; }; @@ -93,7 +98,6 @@ inline bool operator==(const BreakPoint& b1, const BreakPoint& b2) { return b1.compare(b2) == 0; } inline bool operator!=(const BreakPoint& b1, const BreakPoint& b2) { return b1.compare(b2) != 0; } - } #endif // CDBCOREBREAKPOINTS_H diff --git a/src/plugins/debugger/cdb/coreengine.cpp b/src/plugins/debugger/cdb/coreengine.cpp index 8a652ffa4a5..48315cf561d 100644 --- a/src/plugins/debugger/cdb/coreengine.cpp +++ b/src/plugins/debugger/cdb/coreengine.cpp @@ -789,6 +789,22 @@ bool CoreEngine::dissassemble(ULONG64 offset, return true; } +quint64 CoreEngine::getSourceLineAddress(const QString &file, + int line, + QString *errorMessage) const +{ + ULONG64 rc = 0; + const HRESULT hr = m_cif.debugSymbols->GetOffsetByLineWide(line, + const_cast<ushort*>(file.utf16()), + &rc); + if (FAILED(hr)) { + *errorMessage = QString::fromLatin1("Unable to determine address of %1:%2 : %3"). + arg(file).arg(line).arg(msgComFailed("GetOffsetByLine", hr)); + return 0; + } + return rc; +} + bool CoreEngine::autoDetectPath(QString *outPath, QStringList *checkedDirectories /* = 0 */) { diff --git a/src/plugins/debugger/cdb/coreengine.h b/src/plugins/debugger/cdb/coreengine.h index 24968a33ebd..2614f4535c5 100644 --- a/src/plugins/debugger/cdb/coreengine.h +++ b/src/plugins/debugger/cdb/coreengine.h @@ -144,6 +144,8 @@ public: bool dissassemble(ULONG64 offset, unsigned long beforeLines, unsigned long afterLines, QString *target, QString *errorMessage); + quint64 getSourceLineAddress(const QString &file, int line, QString *errorMessage) const; + static bool autoDetectPath(QString *outPath, QStringList *checkedDirectories = 0); diff --git a/tests/manual/ccdb/cdbapplication.cpp b/tests/manual/ccdb/cdbapplication.cpp index ff4d21fcc91..82c120cfe49 100644 --- a/tests/manual/ccdb/cdbapplication.cpp +++ b/tests/manual/ccdb/cdbapplication.cpp @@ -37,6 +37,7 @@ #include <QtCore/QStringList> #include <QtCore/QTimer> +#include <QtCore/QDebug> #include <cstdio> @@ -174,20 +175,30 @@ void CdbApplication::printFrame(const QString &arg) printf("%s\n", qPrintable(errorMessage)); } -bool CdbApplication::queueBreakPoint(const QString &arg) +// Return address or 0 on failure +quint64 CdbApplication::addQueuedBreakPoint(const QString &arg, QString *errorMessage) { // Queue file:line const int cpos = arg.lastIndexOf(QLatin1Char(':')); - if (cpos == -1) - return false; - CdbCore::BreakPoint bp; - bp.fileName = arg.left(cpos); + if (cpos == -1) { + *errorMessage = QString::fromLatin1("Syntax error in '%1': No colon.").arg(arg); + return 0; + } + + const QString fileName = arg.left(cpos); bool ok; - bp.lineNumber = arg.mid(cpos + 1).toInt(&ok); - if (!ok || bp.lineNumber < 1) - return false; - m_queuedBreakPoints.push_back(bp); - return true; + const int lineNumber = arg.mid(cpos + 1).toInt(&ok); + if (!ok || lineNumber < 1) { + *errorMessage = QString::fromLatin1("Syntax error in '%1': No line number.").arg(arg); + return 0; + } + CdbCore::BreakPoint bp; + bp.address = m_engine->getSourceLineAddress(fileName, lineNumber, errorMessage); + if (!bp.address) + return 0; + if (!bp.add(m_engine->interfaces().debugControl, errorMessage)) + return 0; + return bp.address; } void CdbApplication::syncCommand(int command, const QString &arg) @@ -223,11 +234,8 @@ void CdbApplication::syncCommand(int command, const QString &arg) std::printf("Breakpoint queue cleared\n"); m_queuedBreakPoints.clear(); } else { - if (queueBreakPoint(targs)) { - std::printf("Queueing breakpoint %s\n", qPrintable(targs)); - } else { - std::printf("BREAKPOINT SYNTAX ERROR: %s\n", qPrintable(targs)); - } + m_queuedBreakPoints.push_back(targs); + std::printf("Queueing breakpoint %s\n", qPrintable(targs)); } } break; @@ -323,12 +331,12 @@ void CdbApplication::processAttached(void *handle) } } // Breakpoints - foreach(const CdbCore::BreakPoint &bp, m_queuedBreakPoints) { - if (bp.add(m_engine->interfaces().debugControl, &errorMessage)) { - std::printf("'%s' [ok]\n", qPrintable(bp.expression())); + foreach(const QString &bp, m_queuedBreakPoints) { + if (const quint64 address = addQueuedBreakPoint(bp, &errorMessage)) { + std::printf("'%s' 0x%lx [ok]\n", qPrintable(bp), address); } else { std::fprintf(stderr, "%s: %s\n", - qPrintable(bp.expression()), + qPrintable(bp), qPrintable(errorMessage)); } } diff --git a/tests/manual/ccdb/cdbapplication.h b/tests/manual/ccdb/cdbapplication.h index 9a360d43488..432806e8f1c 100644 --- a/tests/manual/ccdb/cdbapplication.h +++ b/tests/manual/ccdb/cdbapplication.h @@ -67,14 +67,14 @@ private slots: private: bool parseOptions(); void printFrame(const QString &arg); - bool queueBreakPoint(const QString &arg); + quint64 addQueuedBreakPoint(const QString &arg, QString *errorMessage); QString m_engineDll; QSharedPointer<CdbCore::CoreEngine> m_engine; QScopedPointer<CdbCore::StackTraceContext> m_stackTrace; CdbPromptThread *m_promptThread; QStringList m_queuedCommands; - QList<CdbCore::BreakPoint> m_queuedBreakPoints; + QStringList m_queuedBreakPoints; void *m_processHandle; }; -- GitLab