Initial work on dumpers for CDB.

Add dumper calls, parser etc. Catch crashes
in the dumper functions.
This commit is contained in:
Friedemann Kleint
2009-04-29 14:15:09 +02:00
parent 3cb783f7fc
commit 72a183777e
22 changed files with 1920 additions and 628 deletions

View File

@@ -29,8 +29,9 @@
#include "cdbdebugengine.h"
#include "cdbdebugengine_p.h"
#include "cdbsymbolgroupcontext.h"
#include "cdbstacktracecontext.h"
#include "cdbstackframecontext.h"
#include "cdbsymbolgroupcontext.h"
#include "cdbbreakpoint.h"
#include "cdbmodules.h"
#include "cdbassembler.h"
@@ -274,7 +275,7 @@ CdbDebugEnginePrivate::CdbDebugEnginePrivate(DebuggerManager *parent,
m_hDebuggeeProcess(0),
m_hDebuggeeThread(0),
m_breakEventMode(BreakEventHandle),
m_dumper(&m_cif),
m_dumper(new CdbDumperHelper(parent, &m_cif)),
m_watchTimer(-1),
m_debugEventCallBack(engine),
m_engine(engine),
@@ -464,7 +465,7 @@ bool CdbDebugEngine::startDebugger()
dumperEnabled = false;
}
}
m_d->m_dumper.reset(dumperLibName, dumperEnabled);
m_d->m_dumper->reset(dumperLibName, dumperEnabled);
m_d->m_debuggerManager->showStatusMessage("Starting Debugger", -1);
QString errorMessage;
bool rc = false;
@@ -590,19 +591,20 @@ void CdbDebugEnginePrivate::processCreatedAttached(ULONG64 processHandle, ULONG6
} else {
m_currentThreadId = 0;
}
// Set initial breakpoints
// Clear any saved breakpoints and set initial breakpoints
m_engine->executeDebuggerCommand(QLatin1String("bc"));
if (m_debuggerManagerAccess->breakHandler()->hasPendingBreakpoints())
m_engine->attemptBreakpointSynchronization();
// At any event, we want a temporary breakpoint at main() to load
// the dumpers.
if (m_dumper.state() == CdbDumperHelper::NotLoaded) {
if (m_dumper->state() == CdbDumperHelper::NotLoaded) {
if (!hasBreakPointAtMain(m_debuggerManagerAccess->breakHandler())) {
QString errorMessage;
CDBBreakPoint mainBP;
// Do not resolve at this point in the rare event someone
// has main in a module
mainBP.funcName = QLatin1String("main");
mainBP.oneShot = true;
QString errorMessage;
if (!mainBP.add(m_cif.debugControl, &errorMessage))
m_debuggerManagerAccess->showQtDumperLibraryWarning(errorMessage);
}
@@ -675,13 +677,13 @@ void CdbDebugEngine::exitDebugger()
killWatchTimer();
}
CdbSymbolGroupContext *CdbDebugEnginePrivate::getStackFrameSymbolGroupContext(int frameIndex, QString *errorMessage) const
CdbStackFrameContext *CdbDebugEnginePrivate::getStackFrameContext(int frameIndex, QString *errorMessage) const
{
if (!m_currentStackTrace) {
*errorMessage = QLatin1String(msgNoStackTraceC);
return 0;
}
if (CdbSymbolGroupContext *sg = m_currentStackTrace->symbolGroupContextAt(frameIndex, errorMessage))
if (CdbStackFrameContext *sg = m_currentStackTrace->frameContextAt(frameIndex, errorMessage))
return sg;
return 0;
}
@@ -718,8 +720,8 @@ bool CdbDebugEnginePrivate::updateLocals(int frameIndex,
}
bool success = false;
if (CdbSymbolGroupContext *sgc = getStackFrameSymbolGroupContext(frameIndex, errorMessage))
success = CdbSymbolGroupContext::populateModelInitially(sgc, wh, errorMessage);
if (CdbStackFrameContext *sgc = getStackFrameContext(frameIndex, errorMessage))
success = sgc->populateModelInitially(wh, errorMessage);
wh->rebuildModel();
return success;
@@ -800,8 +802,8 @@ void CdbDebugEngine::updateWatchModel()
filterEvaluateWatchers(&incomplete, watchHandler);
// Do locals. We might get called while running when someone enters watchers
if (!incomplete.empty()) {
CdbSymbolGroupContext *sg = m_d->m_currentStackTrace->symbolGroupContextAt(frameIndex, &errorMessage);
if (!sg || !CdbSymbolGroupContext::completeModel(sg, incomplete, watchHandler, &errorMessage))
CdbStackFrameContext *sg = m_d->m_currentStackTrace->frameContextAt(frameIndex, &errorMessage);
if (!sg || !sg->completeModel(incomplete, watchHandler, &errorMessage))
break;
}
watchHandler->rebuildModel();
@@ -1016,7 +1018,7 @@ void CdbDebugEngine::assignValueInDebugger(const QString &expr, const QString &v
bool success = false;
do {
QString newValue;
CdbSymbolGroupContext *sg = m_d->getStackFrameSymbolGroupContext(frameIndex, &errorMessage);
CdbStackFrameContext *sg = m_d->getStackFrameContext(frameIndex, &errorMessage);
if (!sg)
break;
if (!sg->assignValue(expr, value, &newValue, &errorMessage))
@@ -1061,17 +1063,30 @@ bool CdbDebugEngine::evaluateExpression(const QString &expression,
QString *value,
QString *type,
QString *errorMessage)
{
DEBUG_VALUE debugValue;
if (!m_d->evaluateExpression(m_d->m_cif.debugControl, expression, &debugValue, errorMessage))
return false;
*value = CdbSymbolGroupContext::debugValueToString(debugValue, m_d->m_cif.debugControl, type);
return true;
}
bool CdbDebugEnginePrivate::evaluateExpression(CIDebugControl *ctrl,
const QString &expression,
DEBUG_VALUE *debugValue,
QString *errorMessage)
{
if (debugCDB > 1)
qDebug() << Q_FUNC_INFO << expression;
DEBUG_VALUE debugValue;
memset(&debugValue, 0, sizeof(DEBUG_VALUE));
memset(debugValue, 0, sizeof(DEBUG_VALUE));
// Original syntax must be restored, else setting breakpoints will fail.
SyntaxSetter syntaxSetter(m_d->m_cif.debugControl, DEBUG_EXPR_CPLUSPLUS);
SyntaxSetter syntaxSetter(ctrl, DEBUG_EXPR_CPLUSPLUS);
ULONG errorPosition = 0;
const HRESULT hr = m_d->m_cif.debugControl->EvaluateWide(expression.utf16(),
DEBUG_VALUE_INVALID, &debugValue,
&errorPosition); if (FAILED(hr)) {
const HRESULT hr = ctrl->EvaluateWide(expression.utf16(),
DEBUG_VALUE_INVALID, debugValue,
&errorPosition);
if (FAILED(hr)) {
if (HRESULT_CODE(hr) == 517) {
*errorMessage = QString::fromLatin1("Unable to evaluate '%1': Expression out of scope.").
arg(expression);
@@ -1081,7 +1096,6 @@ bool CdbDebugEngine::evaluateExpression(const QString &expression,
}
return false;
}
*value = CdbSymbolGroupContext::debugValueToString(debugValue, m_d->m_cif.debugControl, type);
return true;
}
@@ -1355,14 +1369,14 @@ void CdbDebugEnginePrivate::handleDebugEvent()
case BreakEventHandle:
case BreakEventMain:
if (mode == BreakEventMain)
m_dumper.load(m_debuggerManager, m_debuggerManagerAccess);
m_dumper->load(m_debuggerManager);
m_debuggerManagerAccess->notifyInferiorStopped();
updateThreadList();
updateStackTrace();
break;
case BreakEventMainLoadDumpers:
// Temp stop to load dumpers
m_dumper.load(m_debuggerManager, m_debuggerManagerAccess);
m_dumper->load(m_debuggerManager);
m_engine->startWatchTimer();
continueInferiorProcess();
break;
@@ -1436,7 +1450,7 @@ void CdbDebugEnginePrivate::updateStackTrace()
QString errorMessage;
m_engine->reloadRegisters();
m_currentStackTrace =
CdbStackTraceContext::create(&m_cif, m_currentThreadId, &errorMessage);
CdbStackTraceContext::create(m_dumper, m_currentThreadId, &errorMessage);
if (!m_currentStackTrace) {
qWarning("%s: failed to create trace context: %s", Q_FUNC_INFO, qPrintable(errorMessage));
return;