forked from qt-creator/qt-creator
Make break by function work for CDB.
Add function to automagically resolve function symbol names that are missing the module name (module!foo). Kill some trailing whitespace. Add a hack to transform qMain->main for VS.
This commit is contained in:
@@ -28,6 +28,7 @@
|
||||
**************************************************************************/
|
||||
|
||||
#include "cdbbreakpoint.h"
|
||||
#include "cdbmodules.h"
|
||||
#include "breakhandler.h"
|
||||
#include "cdbdebugengine_p.h"
|
||||
|
||||
@@ -279,20 +280,48 @@ bool CDBBreakPoint::getBreakPoints(IDebugControl4* debugControl, QList<CDBBreakP
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
// Synchronize (halted) engine breakpoints with those of the BreakHandler.
|
||||
bool CDBBreakPoint::synchronizeBreakPoints(IDebugControl4* debugControl,
|
||||
IDebugSymbols3 *syms,
|
||||
BreakHandler *handler,
|
||||
QString *errorMessage)
|
||||
{
|
||||
typedef QMap<CDBBreakPoint, int> BreakPointIndexMap;
|
||||
BreakPointIndexMap breakPointIndexMap;
|
||||
// convert BreakHandler's bps into a map of BreakPoint->BreakHandler->Index
|
||||
if (debugCDB)
|
||||
qDebug() << Q_FUNC_INFO;
|
||||
|
||||
BreakPointIndexMap breakPointIndexMap;
|
||||
// convert BreakHandler's bps into a map of BreakPoint->BreakHandler->Index
|
||||
// Ignore invalid functions (that could not be found) as they make
|
||||
// the debugger hang.
|
||||
const int handlerCount = handler->size();
|
||||
for (int i=0; i < handlerCount; ++i)
|
||||
breakPointIndexMap.insert(CDBBreakPoint(*handler->at(i)), i);
|
||||
const QChar moduleDelimiter = QLatin1Char('!');
|
||||
for (int i=0; i < handlerCount; ++i) {
|
||||
BreakpointData *bd = handler->at(i);
|
||||
// Function breakpoints: Are the module names specified?
|
||||
bool breakPointOk = false;
|
||||
if (bd->funcName.isEmpty()) {
|
||||
breakPointOk = true;
|
||||
} else {
|
||||
switch (resolveSymbol(syms, &bd->funcName, errorMessage)) {
|
||||
case ResolveSymbolOk:
|
||||
breakPointOk = true;
|
||||
break;
|
||||
case ResolveSymbolAmbiguous:
|
||||
qWarning("Warning: %s\n", qPrintable(*errorMessage));
|
||||
breakPointOk = true;
|
||||
break;
|
||||
case ResolveSymbolNotFound:
|
||||
case ResolveSymbolError:
|
||||
qWarning("Warning: %s\n", qPrintable(*errorMessage));
|
||||
break;
|
||||
};
|
||||
} // function breakpoint
|
||||
if (breakPointOk)
|
||||
breakPointIndexMap.insert(CDBBreakPoint(*bd), i);
|
||||
}
|
||||
errorMessage->clear();
|
||||
// get number of engine breakpoints
|
||||
ULONG engineCount;
|
||||
if (!getBreakPointCount(debugControl, &engineCount, errorMessage))
|
||||
|
@@ -72,7 +72,8 @@ struct CDBBreakPoint {
|
||||
static bool getBreakPointCount(IDebugControl4* debugControl, ULONG *count, QString *errorMessage = 0);
|
||||
static bool getBreakPoints(IDebugControl4* debugControl, QList<CDBBreakPoint> *bps, QString *errorMessage);
|
||||
// Synchronize (halted) engine with BreakHandler.
|
||||
static bool synchronizeBreakPoints(IDebugControl4* ctl, BreakHandler *bh, QString *errorMessage);
|
||||
static bool synchronizeBreakPoints(IDebugControl4* ctl, IDebugSymbols3 *syms,
|
||||
BreakHandler *bh, QString *errorMessage);
|
||||
|
||||
// Return a 'canonical' file (using '/' and capitalized drive letter)
|
||||
static QString canonicalSourceFile(const QString &f);
|
||||
|
@@ -1032,6 +1032,7 @@ bool CdbDebugEnginePrivate::attemptBreakpointSynchronization(QString *errorMessa
|
||||
}
|
||||
|
||||
return CDBBreakPoint::synchronizeBreakPoints(m_pDebugControl,
|
||||
m_pDebugSymbols,
|
||||
m_debuggerManagerAccess->breakHandler(),
|
||||
errorMessage);
|
||||
}
|
||||
@@ -1260,6 +1261,10 @@ void CdbDebugEnginePrivate::updateStackTrace()
|
||||
qWarning("%s: failed to create trace context: %s", Q_FUNC_INFO, qPrintable(errorMessage));
|
||||
return;
|
||||
}
|
||||
// Disassembling slows things down a bit. Assembler is still available via menu.
|
||||
#if 0
|
||||
m_engine->reloadDisassembler(); // requires stack trace
|
||||
#endif
|
||||
const QList<StackFrame> stackFrames = m_currentStackTrace->frames();
|
||||
// find the first usable frame and select it
|
||||
int current = -1;
|
||||
|
@@ -77,5 +77,61 @@ bool getModuleList(IDebugSymbols3 *syms, QList<Module> *modules, QString *errorM
|
||||
return true;
|
||||
}
|
||||
|
||||
// Search symbols matching a pattern
|
||||
bool searchSymbols(IDebugSymbols3 *syms, const QString &pattern,
|
||||
QStringList *matches, QString *errorMessage)
|
||||
{
|
||||
matches->clear();
|
||||
ULONG64 handle;
|
||||
// E_NOINTERFACE means "no match"
|
||||
HRESULT hr = syms->StartSymbolMatchWide(pattern.utf16(), &handle);
|
||||
if (hr == E_NOINTERFACE) {
|
||||
syms->EndSymbolMatch(handle);
|
||||
return true;
|
||||
}
|
||||
if (FAILED(hr)) {
|
||||
*errorMessage= msgComFailed("StartSymbolMatchWide", hr);
|
||||
return false;
|
||||
}
|
||||
WCHAR wszBuf[MAX_PATH];
|
||||
while (true) {
|
||||
hr = syms->GetNextSymbolMatchWide(handle, wszBuf, MAX_PATH - 1, 0, 0);
|
||||
if (hr == E_NOINTERFACE)
|
||||
break;
|
||||
if (hr == S_OK)
|
||||
matches->push_back(QString::fromUtf16(wszBuf));
|
||||
}
|
||||
syms->EndSymbolMatch(handle);
|
||||
if (matches->empty())
|
||||
*errorMessage = QString::fromLatin1("No symbol matches '%1'.").arg(pattern);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Add missing the module specifier: "main" -> "project!main"
|
||||
|
||||
ResolveSymbolResult resolveSymbol(IDebugSymbols3 *syms, QString *symbol,
|
||||
QString *errorMessage)
|
||||
{
|
||||
// Is it an incomplete symbol?
|
||||
if (symbol->contains(QLatin1Char('!')))
|
||||
return ResolveSymbolOk;
|
||||
// 'main' is a #define for gdb, but not for VS
|
||||
if (*symbol == QLatin1String("qMain"))
|
||||
*symbol = QLatin1String("main");
|
||||
// resolve
|
||||
QStringList matches;
|
||||
if (!searchSymbols(syms, *symbol, &matches, errorMessage))
|
||||
return ResolveSymbolError;
|
||||
if (matches.empty())
|
||||
return ResolveSymbolNotFound;
|
||||
*symbol = matches.front();
|
||||
if (matches.size() > 1) {
|
||||
*errorMessage = QString::fromLatin1("Ambiguous symbol '%1': %2").
|
||||
arg(*symbol, matches.join(QString(QLatin1Char(' '))));
|
||||
return ResolveSymbolAmbiguous;
|
||||
}
|
||||
return ResolveSymbolOk;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
@@ -42,6 +42,17 @@ namespace Internal {
|
||||
class Module;
|
||||
|
||||
bool getModuleList(IDebugSymbols3 *syms, QList<Module> *modules, QString *errorMessage);
|
||||
// Search symbols matching a pattern
|
||||
bool searchSymbols(IDebugSymbols3 *syms, const QString &pattern,
|
||||
QStringList *matches, QString *errorMessage);
|
||||
|
||||
// ResolveSymbol: For symbols that are missing the module specifier,
|
||||
// find the module and expand: "main" -> "project!main".
|
||||
|
||||
enum ResolveSymbolResult { ResolveSymbolOk, ResolveSymbolAmbiguous,
|
||||
ResolveSymbolNotFound, ResolveSymbolError };
|
||||
|
||||
ResolveSymbolResult resolveSymbol(IDebugSymbols3 *syms, QString *symbol, QString *errorMessage);
|
||||
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user