Commit eb05d2ac authored by Friedemann Kleint's avatar Friedemann Kleint
Browse files

CDB CoreEngine: Support break by address for testing purposes.

parent 6d9e3c8a
......@@ -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)
......
......@@ -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
......@@ -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 */)
{
......
......@@ -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);
......
......@@ -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));
}
}
......
......@@ -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;
};
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment