Attach properly, first glimpse of symbols.

This commit is contained in:
Friedemann Kleint
2009-03-06 17:10:23 +01:00
committed by unknown
parent d9cbcdc94b
commit c83782043a
3 changed files with 293 additions and 84 deletions

View File

@@ -44,6 +44,7 @@
#include <QtCore/QFileInfo> #include <QtCore/QFileInfo>
#include <QtCore/QDir> #include <QtCore/QDir>
#include <QtCore/QLibrary> #include <QtCore/QLibrary>
#include <QtCore/QCoreApplication>
#define DBGHELP_TRANSLATE_TCHAR #define DBGHELP_TRANSLATE_TCHAR
#include <inc/Dbghelp.h> #include <inc/Dbghelp.h>
@@ -78,6 +79,16 @@ static QString msgDebugEngineComResult(HRESULT hr)
return Core::Utils::winErrorMessage(HRESULT_CODE(hr)); return Core::Utils::winErrorMessage(HRESULT_CODE(hr));
} }
static QString msgStackIndexOutOfRange(int idx, int size)
{
return QString::fromLatin1("Frame index %1 out of range (%2).").arg(idx).arg(size);
}
static QString msgComFailed(const char *func, HRESULT hr)
{
return QString::fromLatin1("%1 failed: %2").arg(QLatin1String(func), msgDebugEngineComResult(hr));
}
namespace Debugger { namespace Debugger {
namespace Internal { namespace Internal {
@@ -109,52 +120,84 @@ bool DebuggerEngineLibrary::init(QString *errorMessage)
// --- CdbDebugEnginePrivate // --- CdbDebugEnginePrivate
CdbDebugEnginePrivate::CdbDebugEnginePrivate(const DebuggerEngineLibrary &lib, DebuggerManager *parent, CdbDebugEngine* engine) : CdbDebugEnginePrivate::CdbDebugEnginePrivate(DebuggerManager *parent, CdbDebugEngine* engine) :
m_hDebuggeeProcess(0), m_hDebuggeeProcess(0),
m_hDebuggeeThread(0), m_hDebuggeeThread(0),
m_bIgnoreNextDebugEvent(false), m_bIgnoreNextDebugEvent(false),
m_watchTimer(-1), m_watchTimer(-1),
m_debugEventCallBack(engine), m_debugEventCallBack(engine),
m_debugOutputCallBack(engine), m_debugOutputCallBack(engine),
m_pDebugClient(0),
m_pDebugControl(0),
m_pDebugSystemObjects(0),
m_pDebugSymbols(0),
m_pDebugRegisters(0),
m_engine(engine), m_engine(engine),
m_debuggerManager(parent), m_debuggerManager(parent),
m_debuggerManagerAccess(parent->engineInterface()) m_debuggerManagerAccess(parent->engineInterface()),
m_mode(AttachCore)
{ {
}
bool CdbDebugEnginePrivate::init(QString *errorMessage)
{
// Load the DLL
DebuggerEngineLibrary lib;
if (!lib.init(errorMessage))
return false;
// Initialize the COM interfaces
HRESULT hr; HRESULT hr;
hr = lib.debugCreate( __uuidof(IDebugClient5), reinterpret_cast<void**>(&m_pDebugClient)); hr = lib.debugCreate( __uuidof(IDebugClient5), reinterpret_cast<void**>(&m_pDebugClient));
if (FAILED(hr)) { if (FAILED(hr)) {
m_pDebugClient = 0; *errorMessage = QString::fromLatin1("Creation of IDebugClient5 failed: %1").arg(msgDebugEngineComResult(hr));
} else { return false;
}
m_pDebugClient->SetOutputCallbacks(&m_debugOutputCallBack); m_pDebugClient->SetOutputCallbacks(&m_debugOutputCallBack);
m_pDebugClient->SetEventCallbacks(&m_debugEventCallBack); m_pDebugClient->SetEventCallbacks(&m_debugEventCallBack);
}
hr = lib.debugCreate( __uuidof(IDebugControl4), reinterpret_cast<void**>(&m_pDebugControl)); hr = lib.debugCreate( __uuidof(IDebugControl4), reinterpret_cast<void**>(&m_pDebugControl));
if (FAILED(hr)) { if (FAILED(hr)) {
m_pDebugControl = 0; *errorMessage = QString::fromLatin1("Creation of IDebugControl4 failed: %1").arg(msgDebugEngineComResult(hr));
} else { return false;
m_pDebugControl->SetCodeLevel(DEBUG_LEVEL_SOURCE);
} }
m_pDebugControl->SetCodeLevel(DEBUG_LEVEL_SOURCE);
hr = lib.debugCreate( __uuidof(IDebugSystemObjects4), reinterpret_cast<void**>(&m_pDebugSystemObjects)); hr = lib.debugCreate( __uuidof(IDebugSystemObjects4), reinterpret_cast<void**>(&m_pDebugSystemObjects));
if (FAILED(hr)) m_pDebugSystemObjects = 0; if (FAILED(hr)) {
*errorMessage = QString::fromLatin1("Creation of IDebugSystemObjects4 failed: %1").arg(msgDebugEngineComResult(hr));
return false;
}
hr = lib.debugCreate( __uuidof(IDebugSymbols3), reinterpret_cast<void**>(&m_pDebugSymbols)); hr = lib.debugCreate( __uuidof(IDebugSymbols3), reinterpret_cast<void**>(&m_pDebugSymbols));
if (FAILED(hr)) m_pDebugSymbols = 0; if (FAILED(hr)) {
*errorMessage = QString::fromLatin1("Creation of IDebugSymbols3 failed: %1").arg(msgDebugEngineComResult(hr));
return false;
}
hr = lib.debugCreate( __uuidof(IDebugRegisters2), reinterpret_cast<void**>(&m_pDebugRegisters)); hr = lib.debugCreate( __uuidof(IDebugRegisters2), reinterpret_cast<void**>(&m_pDebugRegisters));
if (FAILED(hr)) m_pDebugRegisters = 0; if (FAILED(hr)) {
*errorMessage = QString::fromLatin1("Creation of IDebugRegisters2 failed: %1").arg(msgDebugEngineComResult(hr));
return false;
}
return true;
} }
IDebuggerEngine *CdbDebugEngine::create(DebuggerManager *parent) IDebuggerEngine *CdbDebugEngine::create(DebuggerManager *parent)
{ {
DebuggerEngineLibrary lib;
QString errorMessage; QString errorMessage;
if (!lib.init(&errorMessage)) { IDebuggerEngine *rc = 0;
CdbDebugEngine *e = new CdbDebugEngine(parent);
if (e->m_d->init(&errorMessage)) {
rc = e;
} else {
delete e;
qWarning("%s", qPrintable(errorMessage)); qWarning("%s", qPrintable(errorMessage));
return 0;
} }
return new CdbDebugEngine(lib, parent); return rc;
} }
CdbDebugEnginePrivate::~CdbDebugEnginePrivate() CdbDebugEnginePrivate::~CdbDebugEnginePrivate()
@@ -171,9 +214,9 @@ CdbDebugEnginePrivate::~CdbDebugEnginePrivate()
m_pDebugRegisters->Release(); m_pDebugRegisters->Release();
} }
CdbDebugEngine::CdbDebugEngine(const DebuggerEngineLibrary &lib, DebuggerManager *parent) : CdbDebugEngine::CdbDebugEngine(DebuggerManager *parent) :
IDebuggerEngine(parent), IDebuggerEngine(parent),
m_d(new CdbDebugEnginePrivate(lib, parent, this)) m_d(new CdbDebugEnginePrivate(parent, this))
{ {
} }
@@ -184,12 +227,18 @@ CdbDebugEngine::~CdbDebugEngine()
void CdbDebugEngine::startWatchTimer() void CdbDebugEngine::startWatchTimer()
{ {
if (debugCDB)
qDebug() << Q_FUNC_INFO;
if (m_d->m_watchTimer == -1) if (m_d->m_watchTimer == -1)
m_d->m_watchTimer = startTimer(0); m_d->m_watchTimer = startTimer(0);
} }
void CdbDebugEngine::killWatchTimer() void CdbDebugEngine::killWatchTimer()
{ {
if (debugCDB)
qDebug() << Q_FUNC_INFO;
if (m_d->m_watchTimer != -1) { if (m_d->m_watchTimer != -1) {
killTimer(m_d->m_watchTimer); killTimer(m_d->m_watchTimer);
m_d->m_watchTimer = -1; m_d->m_watchTimer = -1;
@@ -211,7 +260,8 @@ bool CdbDebugEngine::startDebugger()
QString errorMessage; QString errorMessage;
bool rc = false; bool rc = false;
m_d->m_bIgnoreNextDebugEvent = false; m_d->m_bIgnoreNextDebugEvent = false;
switch (m_d->m_debuggerManager->startMode()) { m_d->m_mode = m_d->m_debuggerManager->startMode();
switch (m_d->m_mode) {
case AttachExternal: case AttachExternal:
rc = startAttachDebugger(m_d->m_debuggerManager->m_attachedPID, &errorMessage); rc = startAttachDebugger(m_d->m_debuggerManager->m_attachedPID, &errorMessage);
break; break;
@@ -234,8 +284,10 @@ bool CdbDebugEngine::startDebugger()
bool CdbDebugEngine::startAttachDebugger(unsigned long pid, QString *errorMessage) bool CdbDebugEngine::startAttachDebugger(unsigned long pid, QString *errorMessage)
{ {
// Need to aatrach invasively, otherwise, no notification signals
// for for CreateProcess/ExitProcess occur.
const HRESULT hr = m_d->m_pDebugClient->AttachProcess(NULL, pid, const HRESULT hr = m_d->m_pDebugClient->AttachProcess(NULL, pid,
DEBUG_ATTACH_NONINVASIVE |DEBUG_ATTACH_NONINVASIVE_NO_SUSPEND); DEBUG_ATTACH_INVASIVE_RESUME_PROCESS);
if (debugCDB) if (debugCDB)
qDebug() << "Attaching to " << pid << " returns " << hr; qDebug() << "Attaching to " << pid << " returns " << hr;
if (FAILED(hr)) { if (FAILED(hr)) {
@@ -280,7 +332,7 @@ bool CdbDebugEngine::startDebuggerWithExecutable(QString *errorMessage)
m_d->m_debuggerManager->m_workingDir.utf16(), m_d->m_debuggerManager->m_workingDir.utf16(),
env); env);
if (FAILED(hr)) { if (FAILED(hr)) {
*errorMessage = tr("CreateProcess2Wide failed for '%1': %2").arg(cmd).arg(msgDebugEngineComResult(hr)); *errorMessage = tr("CreateProcess2Wide failed for '%1': %2").arg(cmd, msgDebugEngineComResult(hr));
m_d->m_debuggerManagerAccess->notifyInferiorExited(); m_d->m_debuggerManagerAccess->notifyInferiorExited();
return false; return false;
} }
@@ -293,13 +345,134 @@ void CdbDebugEngine::exitDebugger()
if (debugCDB) if (debugCDB)
qDebug() << Q_FUNC_INFO; qDebug() << Q_FUNC_INFO;
m_d->m_pDebugClient->TerminateCurrentProcess(); if (m_d->m_hDebuggeeProcess) {
// Terminate or detach if we are running
HRESULT hr;
switch (m_d->m_mode) {
case AttachExternal:
if (m_d->isDebuggeeRunning()) { // Process must be stopped in order to detach
DebugBreakProcess(m_d->m_hDebuggeeProcess);
QCoreApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
}
hr = m_d->m_pDebugClient->DetachCurrentProcess();
if (debugCDB)
qDebug() << Q_FUNC_INFO << "detached" << msgDebugEngineComResult(hr);
break;
case StartExternal:
case StartInternal:
hr = m_d->m_pDebugClient->TerminateCurrentProcess();
if (debugCDB)
qDebug() << Q_FUNC_INFO << "terminated" << msgDebugEngineComResult(hr);
break;
case AttachCore:
break;
}
m_d->setDebuggeeHandles(0, 0);
}
killWatchTimer(); killWatchTimer();
} }
bool CdbDebugEnginePrivate::updateLocals(int frameIndex,
WatchHandler *wh,
QString *errorMessage)
{
if (debugCDB)
qDebug() << Q_FUNC_INFO << frameIndex;
CdbStackTrace cdbStackTrace;
if (!getCdbStrackTrace(&cdbStackTrace, errorMessage))
return false;
if ((unsigned)frameIndex >= cdbStackTrace.frameCount) {
*errorMessage = msgStackIndexOutOfRange(frameIndex, cdbStackTrace.frameCount);
return false;
}
IDebugSymbolGroup2 *pDbgSymGroup = 0;
DEBUG_SYMBOL_PARAMETERS *symParams = 0;
bool success = false;
do {
HRESULT hr = m_pDebugSymbols->GetScopeSymbolGroup2(DEBUG_SCOPE_GROUP_LOCALS, NULL, &pDbgSymGroup);
if (FAILED(hr)) {
*errorMessage = msgComFailed("GetScopeSymbolGroup", hr);
break;
}
hr = m_pDebugSymbols->SetScope(0, cdbStackTrace.frames + frameIndex, NULL, 0);
if (FAILED(hr)) {
*errorMessage = msgComFailed("SetScope", hr);
break;
}
// refresh with current frame
hr = m_pDebugSymbols->GetScopeSymbolGroup2(DEBUG_SCOPE_GROUP_LOCALS, pDbgSymGroup, &pDbgSymGroup);
if (FAILED(hr)) {
*errorMessage = msgComFailed("GetScopeSymbolGroup", hr);
break;
}
ULONG symbolCount;
hr = pDbgSymGroup->GetNumberSymbols(&symbolCount);
if (FAILED(hr)) {
*errorMessage = msgComFailed("GetNumberSymbols", hr);
break;
}
symParams = new DEBUG_SYMBOL_PARAMETERS[symbolCount];
hr = pDbgSymGroup->GetSymbolParameters(0, symbolCount, symParams);
if (FAILED(hr)) {
*errorMessage = msgComFailed("GetSymbolParameters", hr);
break;
}
wh->cleanup();
// retrieve symbol names and value strings
ULONG nameLength;
WCHAR nameBuffer[MAX_PATH + 1];
for (ULONG s = 0 ; s < symbolCount ; s++ ) {
// Name
pDbgSymGroup->GetSymbolNameWide(s, nameBuffer, MAX_PATH, &nameLength);
nameBuffer[nameLength] = 0;
const QString name = QString::fromUtf16(nameBuffer);
// Type name
pDbgSymGroup->GetSymbolTypeNameWide(s, nameBuffer, MAX_PATH, &nameLength);
nameBuffer[nameLength] = 0;
const QString type = QString::fromUtf16(nameBuffer);
// Value
QString value;
hr = pDbgSymGroup->GetSymbolValueTextWide(s, nameBuffer, MAX_PATH, &nameLength);
if (SUCCEEDED(hr)) {
nameBuffer[nameLength] = 0;
value = QString::fromUtf16(nameBuffer);
} else {
value = QLatin1String("<unknown>");
}
WatchData wd;
wd.iname = QLatin1String("local");
wd.name = name;
wd.value = value;
wd.type = type;
wd.setAllUnneeded();
wh->insertData(wd);
if (debugCDB)
qDebug() << ' ' << s << '/'<< symbolCount << name << type << value;
}
wh->rebuildModel();
success = true;
} while (false);
delete [] symParams;
if (pDbgSymGroup)
pDbgSymGroup->Release();
return success;
}
void CdbDebugEngine::updateWatchModel() void CdbDebugEngine::updateWatchModel()
{ {
const QList<WatchData> incomplete = m_d->m_debuggerManagerAccess->watchHandler()->takeCurrentIncompletes(); WatchHandler *watchHandler = m_d->m_debuggerManagerAccess->watchHandler();
const QList<WatchData> incomplete = watchHandler->takeCurrentIncompletes();
if (debugCDB) if (debugCDB)
qDebug() << Q_FUNC_INFO << incomplete.size(); qDebug() << Q_FUNC_INFO << incomplete.size();
} }
@@ -464,25 +637,33 @@ void CdbDebugEngine::activateFrame(int frameIndex)
if (m_d->m_debuggerManager->status() != DebuggerInferiorStopped) if (m_d->m_debuggerManager->status() != DebuggerInferiorStopped)
return; return;
QString errorMessage;
bool success = false;
do {
StackHandler *stackHandler = m_d->m_debuggerManagerAccess->stackHandler(); StackHandler *stackHandler = m_d->m_debuggerManagerAccess->stackHandler();
const int oldIndex = stackHandler->currentIndex(); const int oldIndex = stackHandler->currentIndex();
//qDebug() << "ACTIVATE FRAME: " << frameIndex << oldIndex if (frameIndex >= stackHandler->stackSize()) {
// << stackHandler->currentIndex(); errorMessage = msgStackIndexOutOfRange(frameIndex, stackHandler->stackSize());
break;
QTC_ASSERT(frameIndex < stackHandler->stackSize(), return); }
if (oldIndex != frameIndex) { if (oldIndex != frameIndex) {
stackHandler->setCurrentIndex(frameIndex); stackHandler->setCurrentIndex(frameIndex);
//updateLocals(); if (!m_d->updateLocals(frameIndex, m_d->m_debuggerManagerAccess->watchHandler(), &errorMessage))
break;
} }
const StackFrame &frame = stackHandler->currentFrame(); const StackFrame &frame = stackHandler->currentFrame();
if (frame.file.isEmpty() || !QFileInfo(frame.file).isReadable()) {
const bool usable = !frame.file.isEmpty() && QFileInfo(frame.file).isReadable(); errorMessage = QString::fromLatin1("%1: file %2 unusable.").
if (usable) arg(QLatin1String(Q_FUNC_INFO), frame.file);
break;
}
m_d->m_debuggerManager->gotoLocation(frame.file, frame.line, true); m_d->m_debuggerManager->gotoLocation(frame.file, frame.line, true);
else success =true;
qDebug() << "FULL NAME NOT USABLE: " << frame.file; } while (false);
if (!success)
qWarning("%s", qPrintable(errorMessage));
} }
void CdbDebugEngine::selectThread(int index) void CdbDebugEngine::selectThread(int index)
@@ -603,7 +784,7 @@ void CdbDebugEngine::timerEvent(QTimerEvent* te)
case E_PENDING: case E_PENDING:
case E_FAIL: case E_FAIL:
break; break;
case E_UNEXPECTED: case E_UNEXPECTED: // Occurs on ExitProcess.
killWatchTimer(); killWatchTimer();
break; break;
} }
@@ -667,74 +848,85 @@ void CdbDebugEnginePrivate::updateThreadList()
th->setThreads(threads); th->setThreads(threads);
} }
void CdbDebugEnginePrivate::updateStackTrace() // Get CDB stack trace
bool CdbDebugEnginePrivate::getCdbStrackTrace(CdbStackTrace *st, QString *errorMessage)
{ {
if (debugCDB)
qDebug() << Q_FUNC_INFO;
//qDebug() << "updateStackTrace()";
HRESULT hr = m_pDebugSystemObjects->SetCurrentThreadId(m_currentThreadId); HRESULT hr = m_pDebugSystemObjects->SetCurrentThreadId(m_currentThreadId);
if (FAILED(hr)) {
*errorMessage = QString::fromLatin1("%1: SetCurrentThreadId %2 failed: %3").
arg(QString::fromLatin1(Q_FUNC_INFO)).
arg(m_currentThreadId).
arg(msgDebugEngineComResult(hr));
return false;
}
hr = m_pDebugControl->GetStackTrace(0, 0, 0, st->frames, CdbStackTrace::maxFrames, &(st->frameCount));
if (FAILED(hr)) {
*errorMessage = *errorMessage = msgComFailed("GetStackTrace", hr);
return false;
}
return true;
}
//ULONG64 frameOffset, instructionOffset, stackOffset; bool CdbDebugEnginePrivate::getStackTrace(QList<StackFrame> *stackFrames,
//if (FAILED(m_pDebugRegisters->GetFrameOffset2(DEBUG_REGSRC_DEBUGGEE, &frameOffset)) || int *current, QString *errorMessage)
// FAILED(m_pDebugRegisters->GetInstructionOffset2(DEBUG_REGSRC_DEBUGGEE, &instructionOffset)) || {
// FAILED(m_pDebugRegisters->GetStackOffset2(DEBUG_REGSRC_DEBUGGEE, &stackOffset))) stackFrames->clear();
//{ *current = -1;
// frameOffset = instructionOffset = stackOffset = 0; // Get the CDB trace and convert into debugger plugin structures
//} CdbStackTrace cdbStackTrace;
//frameOffset = instructionOffset = stackOffset = 0; if (!getCdbStrackTrace(&cdbStackTrace, errorMessage))
return false;
const ULONG numFrames = 100;
ULONG numFramesFilled = 0;
DEBUG_STACK_FRAME frames[numFrames];
//hr = m_pDebugControl->GetStackTrace(frameOffset, stackOffset, instructionOffset, frames, numFrames, &numFramesFilled);
hr = m_pDebugControl->GetStackTrace(0, 0, 0, frames, numFrames, &numFramesFilled);
if (FAILED(hr))
qDebug() << "GetStackTrace failed";
QList<StackFrame> stackFrames;
WCHAR wszBuf[MAX_PATH]; WCHAR wszBuf[MAX_PATH];
for (ULONG i=0; i < numFramesFilled; ++i) { for (ULONG i=0; i < cdbStackTrace.frameCount; ++i) {
StackFrame frame; StackFrame frame;
frame.line = 0; frame.line = 0;
frame.level = i; frame.level = i;
frame.address = QString::fromLatin1("0x%1").arg(frames[i].InstructionOffset, 0, 16); frame.address = QString::fromLatin1("0x%1").arg(cdbStackTrace.frames[i].InstructionOffset, 0, 16);
m_pDebugSymbols->GetNameByOffsetWide(frames[i].InstructionOffset, wszBuf, MAX_PATH, 0, 0); m_pDebugSymbols->GetNameByOffsetWide(cdbStackTrace.frames[i].InstructionOffset, wszBuf, MAX_PATH, 0, 0);
frame.function = QString::fromUtf16(wszBuf); frame.function = QString::fromUtf16(wszBuf);
ULONG ulLine; ULONG ulLine;
ULONG ulFileNameSize; ULONG ulFileNameSize;
ULONG64 ul64Displacement; ULONG64 ul64Displacement;
hr = m_pDebugSymbols->GetLineByOffsetWide(frames[i].InstructionOffset, &ulLine, wszBuf, MAX_PATH, &ulFileNameSize, &ul64Displacement); const HRESULT hr = m_pDebugSymbols->GetLineByOffsetWide(cdbStackTrace.frames[i].InstructionOffset, &ulLine, wszBuf, MAX_PATH, &ulFileNameSize, &ul64Displacement);
if (SUCCEEDED(hr)) { if (SUCCEEDED(hr)) {
frame.line = ulLine; frame.line = ulLine;
frame.file = QString::fromUtf16(wszBuf, ulFileNameSize); frame.file = QString::fromUtf16(wszBuf, ulFileNameSize);
} }
stackFrames.append(frame); stackFrames->append(frame);
} }
m_debuggerManagerAccess->stackHandler()->setFrames(stackFrames);
// find the first usable frame and select it // find the first usable frame and select it
for (int i=0; i < stackFrames.count(); ++i) { const int count = stackFrames->count();
const StackFrame &frame = stackFrames.at(i); for (int i=0; i < count; ++i) {
const StackFrame &frame = stackFrames->at(i);
const bool usable = !frame.file.isEmpty() && QFileInfo(frame.file).isReadable(); const bool usable = !frame.file.isEmpty() && QFileInfo(frame.file).isReadable();
if (usable) { if (usable) {
m_debuggerManagerAccess->stackHandler()->setCurrentIndex(i); *current = i;
m_debuggerManager->gotoLocation(frame.file, frame.line, true);
break; break;
} }
} }
return true;
}
//m_pDebugSymbols->GetImagePathWide(wszBuf, buflen, 0); void CdbDebugEnginePrivate::updateStackTrace()
//qDebug() << "ImagePath" << QString::fromUtf16(wszBuf); {
//m_pDebugSymbols->GetSymbolPathWide(wszBuf, buflen, 0); if (debugCDB)
//qDebug() << "SymbolPath" << QString::fromUtf16(wszBuf); qDebug() << Q_FUNC_INFO;
QList<StackFrame> stackFrames;
int current;
QString errorMessage;
if (getStackTrace(&stackFrames, &current, &errorMessage))
qWarning("%s", qPrintable(errorMessage));
//m_pDebugControl->OutputStackTrace(DEBUG_OUTCTL_THIS_CLIENT, 0, 2, DEBUG_STACK_FRAME_ADDRESSES | DEBUG_STACK_COLUMN_NAMES | DEBUG_STACK_FRAME_NUMBERS); m_debuggerManagerAccess->stackHandler()->setFrames(stackFrames);
//m_pDebugControl->OutputStackTrace(DEBUG_OUTCTL_THIS_CLIENT, frames, numFramesFilled, DEBUG_STACK_SOURCE_LINE); if (current >= 0) {
m_debuggerManagerAccess->stackHandler()->setCurrentIndex(current);
m_debuggerManager->gotoLocation(stackFrames.at(current).file,
stackFrames.at(current).line, true);
}
} }
void CdbDebugEnginePrivate::handleDebugOutput(const char* szOutputString) void CdbDebugEnginePrivate::handleDebugOutput(const char* szOutputString)

View File

@@ -37,7 +37,6 @@ namespace Internal {
class DebuggerManager; class DebuggerManager;
class CdbDebugEventCallback; class CdbDebugEventCallback;
class DebuggerEngineLibrary;
class CdbDebugOutput; class CdbDebugOutput;
struct CdbDebugEnginePrivate; struct CdbDebugEnginePrivate;
@@ -45,7 +44,7 @@ class CdbDebugEngine : public IDebuggerEngine
{ {
Q_DISABLE_COPY(CdbDebugEngine) Q_DISABLE_COPY(CdbDebugEngine)
Q_OBJECT Q_OBJECT
explicit CdbDebugEngine(const DebuggerEngineLibrary &lib, DebuggerManager *parent); explicit CdbDebugEngine(DebuggerManager *parent);
public: public:
~CdbDebugEngine(); ~CdbDebugEngine();

View File

@@ -32,12 +32,15 @@
#include "cdbdebugeventcallback.h" #include "cdbdebugeventcallback.h"
#include "cdbdebugoutput.h" #include "cdbdebugoutput.h"
#include "stackhandler.h"
#include "debuggermanager.h"
namespace Debugger { namespace Debugger {
namespace Internal { namespace Internal {
class DebuggerManager; class DebuggerManager;
class IDebuggerManagerAccessForEngines; class IDebuggerManagerAccessForEngines;
class WatchHandler;
// Thin wrapper around the 'DBEng' debugger engine shared library // Thin wrapper around the 'DBEng' debugger engine shared library
// which is loaded at runtime. // which is loaded at runtime.
@@ -57,9 +60,20 @@ private:
DebugCreateFunction m_debugCreate; DebugCreateFunction m_debugCreate;
}; };
// Helper struct for stack traces
struct CdbStackTrace {
CdbStackTrace() : frameCount(0) {}
enum { maxFrames = 100 };
ULONG frameCount;
DEBUG_STACK_FRAME frames[maxFrames];
};
struct CdbDebugEnginePrivate struct CdbDebugEnginePrivate
{ {
explicit CdbDebugEnginePrivate(const DebuggerEngineLibrary &lib, DebuggerManager *parent, CdbDebugEngine* engine); explicit CdbDebugEnginePrivate(DebuggerManager *parent, CdbDebugEngine* engine);
bool init(QString *errorMessage);
~CdbDebugEnginePrivate(); ~CdbDebugEnginePrivate();
void setDebuggeeHandles(HANDLE hDebuggeeProcess, HANDLE hDebuggeeThread); void setDebuggeeHandles(HANDLE hDebuggeeProcess, HANDLE hDebuggeeThread);
@@ -68,6 +82,9 @@ struct CdbDebugEnginePrivate
void handleDebugEvent(); void handleDebugEvent();
void updateThreadList(); void updateThreadList();
void updateStackTrace(); void updateStackTrace();
bool updateLocals(int frameIndex, WatchHandler *wh, QString *errorMessage);
bool getCdbStrackTrace(CdbStackTrace *st, QString *errorMessage);
bool getStackTrace(QList<StackFrame> *stackFrames, int *current, QString *errorMessage);
void handleDebugOutput(const char* szOutputString); void handleDebugOutput(const char* szOutputString);
void handleBreakpointEvent(PDEBUG_BREAKPOINT pBP); void handleBreakpointEvent(PDEBUG_BREAKPOINT pBP);
@@ -88,6 +105,7 @@ struct CdbDebugEnginePrivate
CdbDebugEngine* m_engine; CdbDebugEngine* m_engine;
DebuggerManager *m_debuggerManager; DebuggerManager *m_debuggerManager;
IDebuggerManagerAccessForEngines *m_debuggerManagerAccess; IDebuggerManagerAccessForEngines *m_debuggerManagerAccess;
DebuggerStartMode m_mode;
}; };
enum { debugCDB = 0 }; enum { debugCDB = 0 };