Commit 3625e55d authored by ussrhero's avatar ussrhero
Browse files

Merge branch 'patch-1' into 'dev-1.0'

Update dbgmgr.cpp to fix issue 66

See merge request !26
parents 4497f4db 7d47c15a
#include "stdafx.h" #include "stdafx.h"
#include <comutil.h> #include <comutil.h>
#include <kdlib/dbgio.h> #include <kdlib/dbgio.h>
#include "dbgmgr.h" #include "dbgmgr.h"
#include "moduleimp.h" #include "moduleimp.h"
#include "processmon.h" #include "processmon.h"
#include "win/exceptions.h" #include "win/exceptions.h"
namespace kdlib { namespace kdlib {
DebugManagerWrapper g_dbgMgr; DebugManagerWrapper g_dbgMgr;
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
DebugManager::DebugManager() DebugManager::DebugManager()
{ {
m_previousExecutionStatus = DebugStatusNoDebuggee; m_previousExecutionStatus = DebugStatusNoDebuggee;
m_previousCurrentThread = 0; m_previousCurrentThread = 0;
m_remote = false; m_remote = false;
m_quietNotification = false; m_quietNotification = false;
CoInitialize(NULL); CoInitialize(NULL);
HRESULT hres = DebugCreate( __uuidof(IDebugClient4), (void **)&client ); HRESULT hres = DebugCreate( __uuidof(IDebugClient4), (void **)&client );
if ( FAILED( hres ) ) if ( FAILED( hres ) )
throw DbgEngException(L"DebugCreate", hres); throw DbgEngException(L"DebugCreate", hres);
control = CComQIPtr<IDebugControl4>(client); control = CComQIPtr<IDebugControl4>(client);
system = CComQIPtr<IDebugSystemObjects4>(client); system = CComQIPtr<IDebugSystemObjects4>(client);
dataspace = CComQIPtr<IDebugDataSpaces4>(client); dataspace = CComQIPtr<IDebugDataSpaces4>(client);
symbols = CComQIPtr<IDebugSymbols3>(client); symbols = CComQIPtr<IDebugSymbols3>(client);
advanced = CComQIPtr<IDebugAdvanced2>(client); advanced = CComQIPtr<IDebugAdvanced2>(client);
registers = CComQIPtr<IDebugRegisters2>(client); registers = CComQIPtr<IDebugRegisters2>(client);
client->SetEventCallbacksWide( this ); client->SetEventCallbacksWide( this );
client->SetOutputCallbacksWide(this); client->SetOutputCallbacksWide(this);
client->SetInputCallbacks(this); client->SetInputCallbacks(this);
client->SetOutputMask(DEBUG_OUTPUT_NORMAL); client->SetOutputMask(DEBUG_OUTPUT_NORMAL | DEBUG_OUTPUT_ERROR | DEBUG_OUTPUT_WARNING);
} }
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
DebugManager::DebugManager( const std::wstring& remoteOptions ) DebugManager::DebugManager( const std::wstring& remoteOptions )
{ {
m_previousExecutionStatus = DebugStatusNoChange; m_previousExecutionStatus = DebugStatusNoChange;
m_previousCurrentThread = 0; m_previousCurrentThread = 0;
m_remote = true; m_remote = true;
CoInitialize(NULL); CoInitialize(NULL);
HRESULT hres = DebugConnectWide( remoteOptions.c_str(), __uuidof(IDebugClient4), (void **)&client ); HRESULT hres = DebugConnectWide( remoteOptions.c_str(), __uuidof(IDebugClient4), (void **)&client );
if ( FAILED( hres ) ) if ( FAILED( hres ) )
throw DbgEngException(L"DebugConnectWide", hres); throw DbgEngException(L"DebugConnectWide", hres);
hres = client->ConnectSession( 0, 0x1000 ); hres = client->ConnectSession( 0, 0x1000 );
if ( FAILED( hres ) ) if ( FAILED( hres ) )
throw DbgEngException(L"IDebugClient::ConnectSession", hres ); throw DbgEngException(L"IDebugClient::ConnectSession", hres );
control = CComQIPtr<IDebugControl4>(client); control = CComQIPtr<IDebugControl4>(client);
system = CComQIPtr<IDebugSystemObjects4>(client); system = CComQIPtr<IDebugSystemObjects4>(client);
dataspace = CComQIPtr<IDebugDataSpaces4>(client); dataspace = CComQIPtr<IDebugDataSpaces4>(client);
symbols = CComQIPtr<IDebugSymbols3>(client); symbols = CComQIPtr<IDebugSymbols3>(client);
advanced = CComQIPtr<IDebugAdvanced2>(client); advanced = CComQIPtr<IDebugAdvanced2>(client);
registers = CComQIPtr<IDebugRegisters2>(client); registers = CComQIPtr<IDebugRegisters2>(client);
client->SetEventCallbacksWide(this); client->SetEventCallbacksWide(this);
client->SetOutputCallbacksWide(this); client->SetOutputCallbacksWide(this);
client->SetOutputMask(DEBUG_OUTPUT_NORMAL); client->SetOutputMask(DEBUG_OUTPUT_NORMAL | DEBUG_OUTPUT_ERROR | DEBUG_OUTPUT_WARNING);
} }
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
DebugManager::~DebugManager() DebugManager::~DebugManager()
{ {
client->SetEventCallbacks(NULL); client->SetEventCallbacks(NULL);
client->SetOutputCallbacks(NULL); client->SetOutputCallbacks(NULL);
//CoUninitialize(); //CoUninitialize();
} }
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
void DebugManager::registerEventsCallback(DebugEventsCallback *callback) void DebugManager::registerEventsCallback(DebugEventsCallback *callback)
{ {
ProcessMonitor::registerEventsCallback(callback); ProcessMonitor::registerEventsCallback(callback);
} }
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
void DebugManager::removeEventsCallback(DebugEventsCallback *callback) void DebugManager::removeEventsCallback(DebugEventsCallback *callback)
{ {
ProcessMonitor::removeEventsCallback(callback); ProcessMonitor::removeEventsCallback(callback);
} }
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
inline inline
ULONG ConvertCallbackResult( DebugCallbackResult result ) ULONG ConvertCallbackResult( DebugCallbackResult result )
{ {
switch( result ) switch( result )
{ {
case DebugCallbackBreak: case DebugCallbackBreak:
return DEBUG_STATUS_BREAK; return DEBUG_STATUS_BREAK;
case DebugCallbackProceed: case DebugCallbackProceed:
return DEBUG_STATUS_GO_HANDLED; return DEBUG_STATUS_GO_HANDLED;
default: default:
assert( 0 ); assert( 0 );
case DebugCallbackNoChange: case DebugCallbackNoChange:
return DEBUG_STATUS_NO_CHANGE; return DEBUG_STATUS_NO_CHANGE;
} }
} }
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
DebugCallbackResult BreakpointCallbackHandler(IDebugBreakpoint2 *bp); DebugCallbackResult BreakpointCallbackHandler(IDebugBreakpoint2 *bp);
HRESULT STDMETHODCALLTYPE DebugManager::Breakpoint( IDebugBreakpoint2 *bp ) HRESULT STDMETHODCALLTYPE DebugManager::Breakpoint( IDebugBreakpoint2 *bp )
{ {
DebugCallbackResult result = BreakpointCallbackHandler(bp); DebugCallbackResult result = BreakpointCallbackHandler(bp);
return ConvertCallbackResult( result ); return ConvertCallbackResult( result );
} }
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
ExecutionStatus ConvertDbgEngineExecutionStatus( ULONG status ) ExecutionStatus ConvertDbgEngineExecutionStatus( ULONG status )
{ {
switch( status ) switch( status )
{ {
case DEBUG_STATUS_NO_CHANGE: case DEBUG_STATUS_NO_CHANGE:
return DebugStatusNoChange; return DebugStatusNoChange;
case DEBUG_STATUS_GO: case DEBUG_STATUS_GO:
case DEBUG_STATUS_GO_HANDLED: case DEBUG_STATUS_GO_HANDLED:
case DEBUG_STATUS_GO_NOT_HANDLED: case DEBUG_STATUS_GO_NOT_HANDLED:
case DEBUG_STATUS_STEP_OVER: case DEBUG_STATUS_STEP_OVER:
case DEBUG_STATUS_STEP_INTO: case DEBUG_STATUS_STEP_INTO:
case DEBUG_STATUS_STEP_BRANCH: case DEBUG_STATUS_STEP_BRANCH:
case DEBUG_STATUS_IGNORE_EVENT: case DEBUG_STATUS_IGNORE_EVENT:
return DebugStatusGo; return DebugStatusGo;
case DEBUG_STATUS_BREAK: case DEBUG_STATUS_BREAK:
return DebugStatusBreak; return DebugStatusBreak;
case DEBUG_STATUS_NO_DEBUGGEE: case DEBUG_STATUS_NO_DEBUGGEE:
return DebugStatusNoDebuggee; return DebugStatusNoDebuggee;
} }
NOT_IMPLEMENTED(); NOT_IMPLEMENTED();
} }
HRESULT STDMETHODCALLTYPE DebugManager::ChangeEngineState( HRESULT STDMETHODCALLTYPE DebugManager::ChangeEngineState(
__in ULONG Flags, __in ULONG Flags,
__in ULONG64 Argument ) __in ULONG64 Argument )
{ {
try { try {
if (((Flags & DEBUG_CES_EXECUTION_STATUS) != 0) && if (((Flags & DEBUG_CES_EXECUTION_STATUS) != 0) &&
((Argument & DEBUG_STATUS_INSIDE_WAIT) == 0) && ((Argument & DEBUG_STATUS_INSIDE_WAIT) == 0) &&
(ULONG)Argument != m_previousExecutionStatus) (ULONG)Argument != m_previousExecutionStatus)
{ {
if (m_previousExecutionStatus == DEBUG_STATUS_NO_DEBUGGEE && if (m_previousExecutionStatus == DEBUG_STATUS_NO_DEBUGGEE &&
(ULONG)Argument != DEBUG_STATUS_GO) (ULONG)Argument != DEBUG_STATUS_GO)
return S_OK; return S_OK;
ExecutionStatus executionStatus = ConvertDbgEngineExecutionStatus((ULONG)Argument); ExecutionStatus executionStatus = ConvertDbgEngineExecutionStatus((ULONG)Argument);
if (!m_quietNotification) if (!m_quietNotification)
ProcessMonitor::executionStatusChange(executionStatus); ProcessMonitor::executionStatusChange(executionStatus);
m_previousExecutionStatus = (ULONG)Argument; m_previousExecutionStatus = (ULONG)Argument;
} }
if (m_previousExecutionStatus == DEBUG_STATUS_BREAK && if (m_previousExecutionStatus == DEBUG_STATUS_BREAK &&
((Flags & DEBUG_CES_CURRENT_THREAD) != 0) && ((Flags & DEBUG_CES_CURRENT_THREAD) != 0) &&
(m_previousCurrentThread != (ULONG)Argument) && (m_previousCurrentThread != (ULONG)Argument) &&
(DEBUG_ANY_ID != (ULONG)Argument)) (DEBUG_ANY_ID != (ULONG)Argument))
{ {
ULONG threadId = (ULONG)Argument; ULONG threadId = (ULONG)Argument;
if (!m_quietNotification) if (!m_quietNotification)
ProcessMonitor::currentThreadChange(threadId); ProcessMonitor::currentThreadChange(threadId);
m_previousCurrentThread = threadId; m_previousCurrentThread = threadId;
} }
if ((Flags & DEBUG_CES_BREAKPOINTS) != 0) if ((Flags & DEBUG_CES_BREAKPOINTS) != 0)
{ {
ProcessMonitor::breakpointsChange(getCurrentProcessId()); ProcessMonitor::breakpointsChange(getCurrentProcessId());
} }
if ((Flags & DEBUG_CES_EFFECTIVE_PROCESSOR) != 0) if ((Flags & DEBUG_CES_EFFECTIVE_PROCESSOR) != 0)
{ {
if (!m_quietNotification) if (!m_quietNotification)
ProcessMonitor::localScopeChange(); ProcessMonitor::localScopeChange();
} }
} }
catch (kdlib::DbgException&) catch (kdlib::DbgException&)
{ {
} }
return S_OK; return S_OK;
} }
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
HRESULT STDMETHODCALLTYPE DebugManager::Exception( HRESULT STDMETHODCALLTYPE DebugManager::Exception(
__in PEXCEPTION_RECORD64 Exception, __in PEXCEPTION_RECORD64 Exception,
__in ULONG FirstChance ) __in ULONG FirstChance )
{ {
DebugCallbackResult result = DebugCallbackNoChange; DebugCallbackResult result = DebugCallbackNoChange;
try { try {
ExceptionInfo excinfo = {}; ExceptionInfo excinfo = {};
excinfo.firstChance = FirstChance != 0; excinfo.firstChance = FirstChance != 0;
excinfo.exceptionCode = Exception->ExceptionCode; excinfo.exceptionCode = Exception->ExceptionCode;
excinfo.exceptionFlags = Exception->ExceptionFlags; excinfo.exceptionFlags = Exception->ExceptionFlags;
excinfo.exceptionRecord = Exception->ExceptionRecord; excinfo.exceptionRecord = Exception->ExceptionRecord;
excinfo.exceptionAddress = Exception->ExceptionAddress; excinfo.exceptionAddress = Exception->ExceptionAddress;
excinfo.parameterCount = Exception->NumberParameters; excinfo.parameterCount = Exception->NumberParameters;
for (ULONG i = 0; i < Exception->NumberParameters; ++i) for (ULONG i = 0; i < Exception->NumberParameters; ++i)
excinfo.parameters[i] = Exception->ExceptionInformation[i]; excinfo.parameters[i] = Exception->ExceptionInformation[i];
result = ProcessMonitor::exceptionHit(excinfo); result = ProcessMonitor::exceptionHit(excinfo);
} }
catch (kdlib::DbgException&) catch (kdlib::DbgException&)
{ {
} }
return ConvertCallbackResult(result); return ConvertCallbackResult(result);
} }
/////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////
HRESULT STDMETHODCALLTYPE DebugManager::LoadModule( HRESULT STDMETHODCALLTYPE DebugManager::LoadModule(
__in ULONG64 ImageFileHandle, __in ULONG64 ImageFileHandle,
__in ULONG64 BaseOffset, __in ULONG64 BaseOffset,
__in ULONG ModuleSize, __in ULONG ModuleSize,
__in PCWSTR ModuleName, __in PCWSTR ModuleName,
__in PCWSTR ImageName, __in PCWSTR ImageName,
__in ULONG CheckSum, __in ULONG CheckSum,
__in ULONG TimeDateStamp __in ULONG TimeDateStamp
) )
{ {
DebugCallbackResult result = DebugCallbackNoChange; DebugCallbackResult result = DebugCallbackNoChange;
try { try {
std::wstring moduleName = getModuleName(BaseOffset); std::wstring moduleName = getModuleName(BaseOffset);
result = ProcessMonitor::moduleLoad( getCurrentProcessId(), BaseOffset, moduleName); result = ProcessMonitor::moduleLoad( getCurrentProcessId(), BaseOffset, moduleName);
} }
catch (kdlib::DbgException&) catch (kdlib::DbgException&)
{} {}
return ConvertCallbackResult(result); return ConvertCallbackResult(result);
} }
/////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////
HRESULT STDMETHODCALLTYPE DebugManager::UnloadModule( HRESULT STDMETHODCALLTYPE DebugManager::UnloadModule(
__in PCWSTR ImageBaseName, __in PCWSTR ImageBaseName,
__in ULONG64 BaseOffset __in ULONG64 BaseOffset
) )
{ {
DebugCallbackResult result = DebugCallbackNoChange; DebugCallbackResult result = DebugCallbackNoChange;
try { try {
std::wstring moduleName = getModuleName(BaseOffset); std::wstring moduleName = getModuleName(BaseOffset);
result = ProcessMonitor::moduleUnload(getCurrentProcessId(), BaseOffset, moduleName); result = ProcessMonitor::moduleUnload(getCurrentProcessId(), BaseOffset, moduleName);
} }
catch (kdlib::DbgException&) catch (kdlib::DbgException&)
{} {}
return ConvertCallbackResult(result); return ConvertCallbackResult(result);
} }
/////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////
HRESULT STDMETHODCALLTYPE DebugManager::CreateProcess( HRESULT STDMETHODCALLTYPE DebugManager::CreateProcess(
__in ULONG64 ImageFileHandle, __in ULONG64 ImageFileHandle,
__in ULONG64 Handle, __in ULONG64 Handle,
__in ULONG64 BaseOffset, __in ULONG64 BaseOffset,
__in ULONG ModuleSize, __in ULONG ModuleSize,
__in PCWSTR ModuleName, __in PCWSTR ModuleName,
__in PCWSTR ImageName, __in PCWSTR ImageName,
__in ULONG CheckSum, __in ULONG CheckSum,
__in ULONG TimeDateStamp, __in ULONG TimeDateStamp,
__in ULONG64 InitialThreadHandle, __in ULONG64 InitialThreadHandle,
__in ULONG64 ThreadDataOffset, __in ULONG64 ThreadDataOffset,
__in ULONG64 StartOffset __in ULONG64 StartOffset
) )
{ {
DebugCallbackResult result = DebugCallbackNoChange; DebugCallbackResult result = DebugCallbackNoChange;
try { try {
PROCESS_DEBUG_ID processId = getCurrentProcessId(); PROCESS_DEBUG_ID processId = getCurrentProcessId();
result = ProcessMonitor::processStart(processId); result = ProcessMonitor::processStart(processId);
ProcessMonitor::moduleLoad(processId, BaseOffset, std::wstring(ModuleName)); ProcessMonitor::moduleLoad(processId, BaseOffset, std::wstring(ModuleName));
} }
catch (kdlib::DbgException&) catch (kdlib::DbgException&)
{ {
} }
return ConvertCallbackResult( result ); return ConvertCallbackResult( result );
} }
/////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////
HRESULT STDMETHODCALLTYPE DebugManager::ExitProcess( HRESULT STDMETHODCALLTYPE DebugManager::ExitProcess(
__in ULONG ExitCode __in ULONG ExitCode
) )
{ {
DebugCallbackResult result = DebugCallbackNoChange; DebugCallbackResult result = DebugCallbackNoChange;
try { try {
PROCESS_DEBUG_ID procId = getCurrentProcessId(); PROCESS_DEBUG_ID procId = getCurrentProcessId();
result = ProcessMonitor::processStop(procId, ProcessExit, ExitCode); result = ProcessMonitor::processStop(procId, ProcessExit, ExitCode);
} }
catch (kdlib::DbgException&) catch (