Commit 3695ee36 authored by Friedemann Kleint's avatar Friedemann Kleint

Start on dumper support for CDB, bug fixes.

Make command execution output shown, use Wide version
of Debug Callbacks and output, provide bases classes
for other output and event handlers, move common
dumper functionality into debugger manager.
parent 89204263
......@@ -37,7 +37,8 @@ HEADERS += \
$$PWD/cdbmodules.h \
$$PWD/cdbassembler.h \
$$PWD/cdboptions.h \
$$PWD/cdboptionspage.h
$$PWD/cdboptionspage.h \
$$PWD/cdbdumperhelper.h
SOURCES += \
$$PWD/cdbdebugengine.cpp \
......@@ -49,7 +50,8 @@ SOURCES += \
$$PWD/cdbmodules.cpp \
$$PWD/cdbassembler.cpp \
$$PWD/cdboptions.cpp \
$$PWD/cdboptionspage.cpp
$$PWD/cdboptionspage.cpp \
$$PWD/cdbdumperhelper.cpp
FORMS += $$PWD/cdboptionspagewidget.ui
......
......@@ -212,14 +212,11 @@ bool dissassemble(IDebugClient5 *client,
// in assembler code). We build a complete string first as line breaks
// may occur in-between messages.
StringOutputHandler stringHandler;
IDebugOutputCallbacksWide *oldHandler = CdbDebugOutputBase::getOutputCallback(client);
client->SetOutputCallbacksWide(&stringHandler);
OutputRedirector redir(client, &stringHandler);
// For some reason, we need to output to "all clients"
const HRESULT hr = ctl->OutputDisassemblyLines(DEBUG_OUTCTL_ALL_CLIENTS,
beforeLines, beforeLines + afterLines,
offset, flags, 0, 0, 0, 0);
client->SetOutputCallbacksWide(oldHandler);
if (FAILED(hr)) {
*errorMessage= QString::fromLatin1("Unable to dissamble at 0x%1: %2").
arg(QString::number(offset, 16), msgComFailed("OutputDisassemblyLines", hr));
......
This diff is collapsed.
......@@ -33,6 +33,7 @@
#include "cdbdebugeventcallback.h"
#include "cdbdebugoutput.h"
#include "cdboptions.h"
#include "cdbdumperhelper.h"
#include "stackhandler.h"
#include "debuggermanager.h"
......@@ -67,6 +68,31 @@ private:
DebugCreateFunction m_debugCreate;
};
// A class that sets an expression syntax on the debug control while in scope.
// Can be nested as it checks for the old value.
class SyntaxSetter {
Q_DISABLE_COPY(SyntaxSetter)
public:
explicit inline SyntaxSetter(IDebugControl4 *ctl, ULONG desiredSyntax);
inline ~SyntaxSetter();
private:
const ULONG m_desiredSyntax;
IDebugControl4 *m_ctl;
ULONG m_oldSyntax;
};
// helper struct to pass interfaces around
struct CdbComInterfaces
{
CdbComInterfaces();
IDebugClient5* debugClient;
IDebugControl4* debugControl;
IDebugSystemObjects4* debugSystemObjects;
IDebugSymbols3* debugSymbols;
IDebugRegisters2* debugRegisters;
IDebugDataSpaces4* debugDataSpaces;
};
struct CdbDebugEnginePrivate
{
enum HandleBreakEventMode { // Special modes for break event handler.
......@@ -90,9 +116,10 @@ struct CdbDebugEnginePrivate
bool updateLocals(int frameIndex, WatchHandler *wh, QString *errorMessage);
void updateModules();
void handleBreakpointEvent(PDEBUG_BREAKPOINT pBP);
void handleBreakpointEvent(PDEBUG_BREAKPOINT2 pBP);
void cleanStackTrace();
void clearForRun();
void handleModuleLoad(const QString &);
CdbSymbolGroupContext *getStackFrameSymbolGroupContext(int frameIndex, QString *errorMessage) const;
void clearDisplay();
......@@ -103,6 +130,8 @@ struct CdbDebugEnginePrivate
bool attemptBreakpointSynchronization(QString *errorMessage);
static bool executeDebuggerCommand(IDebugControl4 *ctrl, const QString &command, QString *errorMessage);
const QSharedPointer<CdbOptions> m_options;
HANDLE m_hDebuggeeProcess;
HANDLE m_hDebuggeeThread;
......@@ -110,13 +139,10 @@ struct CdbDebugEnginePrivate
HandleBreakEventMode m_breakEventMode;
int m_watchTimer;
IDebugClient5* m_pDebugClient;
IDebugControl4* m_pDebugControl;
IDebugSystemObjects4* m_pDebugSystemObjects;
IDebugSymbols3* m_pDebugSymbols;
IDebugRegisters2* m_pDebugRegisters;
CdbComInterfaces m_cif;
CdbDebugEventCallback m_debugEventCallBack;
CdbDebugOutput m_debugOutputCallBack;
CdbDebugOutput m_debugOutputCallBack;
CdbDumperHelper m_dumper;
CdbDebugEngine* m_engine;
DebuggerManager *m_debuggerManager;
......
......@@ -38,12 +38,12 @@
namespace Debugger {
namespace Internal {
CdbDebugEventCallback::CdbDebugEventCallback(CdbDebugEngine* dbg) :
m_pEngine(dbg)
// CdbDebugEventCallbackBase
CdbDebugEventCallbackBase::CdbDebugEventCallbackBase()
{
}
STDMETHODIMP CdbDebugEventCallback::QueryInterface(
STDMETHODIMP CdbDebugEventCallbackBase::QueryInterface(
THIS_
IN REFIID InterfaceId,
OUT PVOID* Interface)
......@@ -60,32 +60,170 @@ STDMETHODIMP CdbDebugEventCallback::QueryInterface(
}
}
STDMETHODIMP_(ULONG) CdbDebugEventCallback::AddRef(THIS)
STDMETHODIMP_(ULONG) CdbDebugEventCallbackBase::AddRef(THIS)
{
// This class is designed to be static so
// there's no true refcount.
return 1;
}
STDMETHODIMP_(ULONG) CdbDebugEventCallback::Release(THIS)
STDMETHODIMP_(ULONG) CdbDebugEventCallbackBase::Release(THIS)
{
// This class is designed to be static so
// there's no true refcount.
return 0;
}
STDMETHODIMP CdbDebugEventCallbackBase::Breakpoint(THIS_ __in PDEBUG_BREAKPOINT2)
{
return S_OK;
}
STDMETHODIMP CdbDebugEventCallbackBase::Exception(
THIS_
__in PEXCEPTION_RECORD64,
__in ULONG /* FirstChance */
)
{
return S_OK;
}
STDMETHODIMP CdbDebugEventCallbackBase::CreateThread(
THIS_
__in ULONG64 /* Handle */,
__in ULONG64 /* DataOffset */,
__in ULONG64 /* StartOffset */
)
{
return S_OK;
}
STDMETHODIMP CdbDebugEventCallbackBase::ExitThread(
THIS_
__in ULONG /* ExitCode */
)
{
return S_OK;
}
STDMETHODIMP CdbDebugEventCallbackBase::CreateProcess(
THIS_
__in ULONG64 /* ImageFileHandle */,
__in ULONG64 /* Handle */,
__in ULONG64 /* BaseOffset */,
__in ULONG /* ModuleSize */,
__in_opt PCWSTR /* ModuleName */,
__in_opt PCWSTR /* ImageName */,
__in ULONG /* CheckSum */,
__in ULONG /* TimeDateStamp */,
__in ULONG64 /* InitialThreadHandle */,
__in ULONG64 /* ThreadDataOffset */,
__in ULONG64 /* StartOffset */
)
{
return S_OK;
}
STDMETHODIMP CdbDebugEventCallbackBase::ExitProcess(
THIS_
__in ULONG /* ExitCode */
)
{
return S_OK;
}
STDMETHODIMP CdbDebugEventCallbackBase::LoadModule(
THIS_
__in ULONG64 /* ImageFileHandle */,
__in ULONG64 /* BaseOffset */,
__in ULONG /* ModuleSize */,
__in_opt PCWSTR /* ModuleName */,
__in_opt PCWSTR /* ImageName */,
__in ULONG /* CheckSum */,
__in ULONG /* TimeDateStamp */
)
{
return S_OK;
}
STDMETHODIMP CdbDebugEventCallbackBase::UnloadModule(
THIS_
__in_opt PCWSTR /* ImageBaseName */,
__in ULONG64 /* BaseOffset */
)
{
return S_OK;
}
STDMETHODIMP CdbDebugEventCallbackBase::SystemError(
THIS_
__in ULONG /* Error */,
__in ULONG /* Level */
)
{
return S_OK;
}
STDMETHODIMP CdbDebugEventCallbackBase::SessionStatus(
THIS_
__in ULONG /* Status */
)
{
return S_OK;
}
STDMETHODIMP CdbDebugEventCallbackBase::ChangeDebuggeeState(
THIS_
__in ULONG /* Flags */,
__in ULONG64 /* Argument */
)
{
return S_OK;
}
STDMETHODIMP CdbDebugEventCallbackBase::ChangeEngineState(
THIS_
__in ULONG /* Flags */,
__in ULONG64 /* Argument */
)
{
return S_OK;
}
STDMETHODIMP CdbDebugEventCallbackBase::ChangeSymbolState(
THIS_
__in ULONG /* Flags */,
__in ULONG64 /* Argument */
)
{
return S_OK;
}
IDebugEventCallbacksWide *CdbDebugEventCallbackBase::getEventCallback(IDebugClient5 *clnt)
{
IDebugEventCallbacksWide *rc = 0;
if (SUCCEEDED(clnt->GetEventCallbacksWide(&rc)))
return rc;
return 0;
}
// ---------- CdbDebugEventCallback
CdbDebugEventCallback::CdbDebugEventCallback(CdbDebugEngine* dbg) :
m_pEngine(dbg)
{
}
STDMETHODIMP CdbDebugEventCallback::GetInterestMask(THIS_ __out PULONG mask)
{
*mask = DEBUG_EVENT_CREATE_PROCESS | DEBUG_EVENT_EXIT_PROCESS
| DEBUG_EVENT_LOAD_MODULE | DEBUG_EVENT_UNLOAD_MODULE
| DEBUG_EVENT_CREATE_THREAD | DEBUG_EVENT_EXIT_THREAD
| DEBUG_EVENT_BREAKPOINT
| DEBUG_EVENT_EXCEPTION
;
| DEBUG_EVENT_EXCEPTION;
return S_OK;
}
STDMETHODIMP CdbDebugEventCallback::Breakpoint(THIS_ __in PDEBUG_BREAKPOINT Bp)
STDMETHODIMP CdbDebugEventCallback::Breakpoint(THIS_ __in PDEBUG_BREAKPOINT2 Bp)
{
if (debugCDB)
qDebug() << Q_FUNC_INFO;
......@@ -150,8 +288,8 @@ STDMETHODIMP CdbDebugEventCallback::CreateProcess(
__in ULONG64 Handle,
__in ULONG64 BaseOffset,
__in ULONG ModuleSize,
__in_opt PCSTR ModuleName,
__in_opt PCSTR ImageName,
__in_opt PCWSTR ModuleName,
__in_opt PCWSTR ImageName,
__in ULONG CheckSum,
__in ULONG TimeDateStamp,
__in ULONG64 InitialThreadHandle,
......@@ -175,7 +313,7 @@ STDMETHODIMP CdbDebugEventCallback::CreateProcess(
m_pEngine->m_d->m_debuggerManagerAccess->notifyInferiorRunning();
ULONG currentThreadId;
if (SUCCEEDED(m_pEngine->m_d->m_pDebugSystemObjects->GetThreadIdByHandle(InitialThreadHandle, &currentThreadId)))
if (SUCCEEDED(m_pEngine->m_d->m_cif.debugSystemObjects->GetThreadIdByHandle(InitialThreadHandle, &currentThreadId)))
m_pEngine->m_d->m_currentThreadId = currentThreadId;
else
m_pEngine->m_d->m_currentThreadId = 0;
......@@ -201,8 +339,8 @@ STDMETHODIMP CdbDebugEventCallback::LoadModule(
__in ULONG64 ImageFileHandle,
__in ULONG64 BaseOffset,
__in ULONG ModuleSize,
__in_opt PCSTR ModuleName,
__in_opt PCSTR ImageName,
__in_opt PCWSTR ModuleName,
__in_opt PCWSTR ImageName,
__in ULONG CheckSum,
__in ULONG TimeDateStamp
)
......@@ -216,13 +354,13 @@ STDMETHODIMP CdbDebugEventCallback::LoadModule(
Q_UNUSED(TimeDateStamp)
if (debugCDB > 1)
qDebug() << Q_FUNC_INFO << ModuleName;
m_pEngine->m_d->updateModules();
m_pEngine->m_d->handleModuleLoad(QString::fromUtf16(ModuleName));
return S_OK;
}
STDMETHODIMP CdbDebugEventCallback::UnloadModule(
THIS_
__in_opt PCSTR ImageBaseName,
__in_opt PCWSTR ImageBaseName,
__in ULONG64 BaseOffset
)
{
......@@ -245,46 +383,28 @@ STDMETHODIMP CdbDebugEventCallback::SystemError(
return S_OK;
}
STDMETHODIMP CdbDebugEventCallback::SessionStatus(
THIS_
__in ULONG Status
)
// -----------IgnoreDebugEventCallback
IgnoreDebugEventCallback::IgnoreDebugEventCallback()
{
Q_UNUSED(Status)
return S_OK;
}
STDMETHODIMP CdbDebugEventCallback::ChangeDebuggeeState(
THIS_
__in ULONG Flags,
__in ULONG64 Argument
)
STDMETHODIMP IgnoreDebugEventCallback::GetInterestMask(THIS_ __out PULONG mask)
{
Q_UNUSED(Flags)
Q_UNUSED(Argument)
*mask = 0;
return S_OK;
}
STDMETHODIMP CdbDebugEventCallback::ChangeEngineState(
THIS_
__in ULONG Flags,
__in ULONG64 Argument
)
// --------- EventCallbackRedirector
EventCallbackRedirector::EventCallbackRedirector(IDebugClient5 *client, IDebugEventCallbacksWide *cb) :
m_client(client),
m_oldCb(CdbDebugEventCallbackBase::getEventCallback(client))
{
Q_UNUSED(Flags)
Q_UNUSED(Argument)
return S_OK;
client->SetEventCallbacksWide(cb);
}
STDMETHODIMP CdbDebugEventCallback::ChangeSymbolState(
THIS_
__in ULONG Flags,
__in ULONG64 Argument
)
EventCallbackRedirector::~EventCallbackRedirector()
{
Q_UNUSED(Flags)
Q_UNUSED(Argument)
return S_OK;
m_client->SetEventCallbacksWide(m_oldCb);
}
} // namespace Internal
......
......@@ -32,17 +32,21 @@
#include <windows.h>
#include <inc/dbgeng.h>
#include <QtCore/QtGlobal>
namespace Debugger {
namespace Internal {
class CdbDebugEngine;
class CdbDebugEventCallback : public IDebugEventCallbacks
// Base class for event callbacks that takes care
// Active X magic. Provides base implementations with
// the exception of GetInterestMask
class CdbDebugEventCallbackBase : public IDebugEventCallbacksWide
{
protected:
CdbDebugEventCallbackBase();
public:
explicit CdbDebugEventCallback(CdbDebugEngine* dbg);
// IUnknown.
STDMETHOD(QueryInterface)(
THIS_
......@@ -58,14 +62,9 @@ public:
// IDebugEventCallbacks.
STDMETHOD(GetInterestMask)(
THIS_
__out PULONG mask
);
STDMETHOD(Breakpoint)(
THIS_
__in PDEBUG_BREAKPOINT Bp
__in PDEBUG_BREAKPOINT2 Bp
);
STDMETHOD(Exception)(
......@@ -91,8 +90,8 @@ public:
__in ULONG64 Handle,
__in ULONG64 BaseOffset,
__in ULONG ModuleSize,
__in_opt PCSTR ModuleName,
__in_opt PCSTR ImageName,
__in_opt PCWSTR ModuleName,
__in_opt PCWSTR ImageName,
__in ULONG CheckSum,
__in ULONG TimeDateStamp,
__in ULONG64 InitialThreadHandle,
......@@ -110,15 +109,15 @@ public:
__in ULONG64 ImageFileHandle,
__in ULONG64 BaseOffset,
__in ULONG ModuleSize,
__in_opt PCSTR ModuleName,
__in_opt PCSTR ImageName,
__in_opt PCWSTR ModuleName,
__in_opt PCWSTR ImageName,
__in ULONG CheckSum,
__in ULONG TimeDateStamp
);
STDMETHOD(UnloadModule)(
THIS_
__in_opt PCSTR ImageBaseName,
__in_opt PCWSTR ImageBaseName,
__in ULONG64 BaseOffset
);
......@@ -151,10 +150,116 @@ public:
__in ULONG64 Argument
);
static IDebugEventCallbacksWide *getEventCallback(IDebugClient5 *clnt);
};
class CdbDebugEventCallback : public CdbDebugEventCallbackBase
{
public:
explicit CdbDebugEventCallback(CdbDebugEngine* dbg);
// IDebugEventCallbacks.
STDMETHOD(GetInterestMask)(
THIS_
__out PULONG mask
);
STDMETHOD(Breakpoint)(
THIS_
__in PDEBUG_BREAKPOINT2 Bp
);
STDMETHOD(Exception)(
THIS_
__in PEXCEPTION_RECORD64 Exception,
__in ULONG FirstChance
);
STDMETHOD(CreateThread)(
THIS_
__in ULONG64 Handle,
__in ULONG64 DataOffset,
__in ULONG64 StartOffset
);
STDMETHOD(ExitThread)(
THIS_
__in ULONG ExitCode
);
STDMETHOD(CreateProcess)(
THIS_
__in ULONG64 ImageFileHandle,
__in ULONG64 Handle,
__in ULONG64 BaseOffset,
__in ULONG ModuleSize,
__in_opt PCWSTR ModuleName,
__in_opt PCWSTR ImageName,
__in ULONG CheckSum,
__in ULONG TimeDateStamp,
__in ULONG64 InitialThreadHandle,
__in ULONG64 ThreadDataOffset,
__in ULONG64 StartOffset
);
STDMETHOD(ExitProcess)(
THIS_
__in ULONG ExitCode
);
STDMETHOD(LoadModule)(
THIS_
__in ULONG64 ImageFileHandle,
__in ULONG64 BaseOffset,
__in ULONG ModuleSize,
__in_opt PCWSTR ModuleName,
__in_opt PCWSTR ImageName,
__in ULONG CheckSum,
__in ULONG TimeDateStamp
);
STDMETHOD(UnloadModule)(
THIS_
__in_opt PCWSTR ImageBaseName,
__in ULONG64 BaseOffset
);
STDMETHOD(SystemError)(
THIS_
__in ULONG Error,
__in ULONG Level
);
private:
CdbDebugEngine *m_pEngine;
};
// Event handler that ignores everything
class IgnoreDebugEventCallback : public CdbDebugEventCallbackBase
{
public:
explicit IgnoreDebugEventCallback();
STDMETHOD(GetInterestMask)(
THIS_
__out PULONG mask
);
};
// Utility class to temporarily redirect events to another handler
// as long as in scope
class EventCallbackRedirector {
Q_DISABLE_COPY(EventCallbackRedirector)
public:
explicit EventCallbackRedirector(IDebugClient5 *client, IDebugEventCallbacksWide *cb);
~EventCallbackRedirector();
private:
IDebugClient5 *m_client;
IDebugEventCallbacksWide *m_oldCb;
};
} // namespace Internal
} // namespace Debugger
......
......@@ -155,5 +155,18 @@ void CdbDebugOutput::output(ULONG mask, const QString &msg)
}
}
// Utility class to temporarily redirect output to another handler
// as long as in scope
OutputRedirector::OutputRedirector(IDebugClient5 *client, IDebugOutputCallbacksWide *newHandler) :
m_client(client),
m_oldHandler(CdbDebugOutputBase::getOutputCallback(client))
{
m_client->SetOutputCallbacksWide(newHandler);
}
OutputRedirector::~OutputRedirector()
{
m_client->SetOutputCallbacksWide(m_oldHandler);
}
} // namespace Internal
} // namespace Debugger
......@@ -105,6 +105,18 @@ private:
QString m_result;
};
// Utility class to temporarily redirect output to another handler
// as long as in scope
class OutputRedirector {
Q_DISABLE_COPY(OutputRedirector)
public:
explicit OutputRedirector(IDebugClient5 *client, IDebugOutputCallbacksWide *newHandler);
~OutputRedirector();
private:
IDebugClient5 *m_client;
IDebugOutputCallbacksWide *m_oldHandler;
};
} // namespace Internal
} // namespace Debugger
......
/**************************************************************************
**
** This file is part of Qt Creator