initial breakpoint work + added MemIsValidPtr + fixed some documentation inaccuracies

This commit is contained in:
mrexodia 2015-08-09 00:53:13 +02:00
parent 43415e12aa
commit 3568de5680
12 changed files with 297 additions and 40 deletions

View File

@ -0,0 +1,78 @@
#ifndef _DEBUGGER_BREAKPOINT_H
#define _DEBUGGER_BREAKPOINT_H
#include "Debugger.Global.h"
namespace GleeBug
{
enum class BreakpointType
{
Software,
Hardware,
Memory
};
enum class SoftwareBreakpointType
{
ShortInt3
};
enum class HardwareBreakpointType
{
Access,
Write,
Execute
};
enum class HardwareBreakpointSize
{
SizeByte,
SizeWord,
SizeDword,
#ifdef _WIN64
SizeQword
#endif //_WIN64
};
enum class MemoryBreakpointType
{
Acess,
Write,
Execute
};
struct BreakpointInternalInfo
{
union
{
struct
{
SoftwareBreakpointType type;
ptr size;
uint8 newbytes[2];
uint8 oldbytes[2];
} software;
struct
{
HardwareBreakpointType type;
HardwareBreakpointSize size;
} hardware;
struct
{
MemoryBreakpointType type;
ptr size;
} memory;
};
};
struct BreakpointInfo
{
ptr address;
bool enabled;
bool singleshoot;
BreakpointType type;
BreakpointInternalInfo internal;
};
};
#endif //_DEBUGGER_BREAKPOINT_H

View File

@ -10,14 +10,22 @@ namespace GleeBug
class ProcessInfo; class ProcessInfo;
class DllInfo; class DllInfo;
class ThreadInfo; class ThreadInfo;
enum class BreakpointType;
struct BreakpointInfo;
//key typedefs
typedef std::pair<BreakpointType, ptr> BreakpointKey;
//callback function typedefs
typedef std::function<void()> StepCallback;
typedef std::function<void(const BreakpointInfo & info)> BreakpointCallback;
//map typedefs //map typedefs
typedef std::map<uint32, ProcessInfo> ProcessMap; typedef std::map<uint32, ProcessInfo> ProcessMap;
typedef std::map<Range, DllInfo, RangeCompare> DllMap; typedef std::map<Range, DllInfo, RangeCompare> DllMap;
typedef std::map<uint32, ThreadInfo> ThreadMap; typedef std::map<uint32, ThreadInfo> ThreadMap;
typedef std::map<BreakpointKey, BreakpointInfo> BreakpointMap;
//callback function typedefs typedef std::map<BreakpointKey, BreakpointCallback> BreakpointCallbackMap;
typedef std::function<void()> StepCallback;
//vector typedefs //vector typedefs
typedef std::vector<StepCallback> StepCallbackVector; typedef std::vector<StepCallback> StepCallbackVector;

View File

@ -6,27 +6,50 @@ namespace GleeBug
{ {
if (!_process->systemBreakpoint) //handle system breakpoint if (!_process->systemBreakpoint) //handle system breakpoint
{ {
//set internal state
_process->systemBreakpoint = true; _process->systemBreakpoint = true;
_continueStatus = DBG_CONTINUE; _continueStatus = DBG_CONTINUE;
//call the callback //call the callback
cbSystemBreakpoint(); cbSystemBreakpoint();
} }
else
{
//check if the breakpoint exists
auto foundInfo = _process->breakpoints.find({ BreakpointType::Software, ptr(exceptionRecord.ExceptionAddress) });
if (foundInfo == _process->breakpoints.end())
return;
const auto & info = foundInfo->second;
//set continue status
_continueStatus = DBG_CONTINUE;
//call the generic callback
cbBreakpoint(info);
//call the user callback
auto foundCallback = _process->breakpointCallbacks.find({ BreakpointType::Software, info.address });
if (foundCallback != _process->breakpointCallbacks.end())
foundCallback->second(info);
}
} }
void Debugger::exceptionSingleStep(const EXCEPTION_RECORD & exceptionRecord, const bool firstChance) void Debugger::exceptionSingleStep(const EXCEPTION_RECORD & exceptionRecord, const bool firstChance)
{ {
if (_thread->isSingleStepping) //handle single step if (_thread->isSingleStepping) //handle single step
{ {
//set internal status
_thread->isSingleStepping = false; _thread->isSingleStepping = false;
_continueStatus = DBG_CONTINUE; _continueStatus = DBG_CONTINUE;
//call the callbacks //call the generic callback
StepCallbackVector cbStepCopy = _thread->stepCallbacks; cbStep();
//call the user callbacks
auto cbStepCopy = _thread->stepCallbacks;
_thread->stepCallbacks.clear(); _thread->stepCallbacks.clear();
for (auto cbStep : cbStepCopy) for (auto cbStep : cbStepCopy)
cbStep(); cbStep();
cbStep();
} }
else //handle other single step exceptions else //handle other single step exceptions
{ {
@ -39,7 +62,10 @@ namespace GleeBug
_continueStatus = DBG_EXCEPTION_NOT_HANDLED; _continueStatus = DBG_EXCEPTION_NOT_HANDLED;
const EXCEPTION_RECORD & exceptionRecord = exceptionInfo.ExceptionRecord; const EXCEPTION_RECORD & exceptionRecord = exceptionInfo.ExceptionRecord;
const bool firstChance = exceptionInfo.dwFirstChance == 1; bool firstChance = exceptionInfo.dwFirstChance == 1;
//call the debug event callback
cbExceptionEvent(exceptionInfo);
//dispatch the exception //dispatch the exception
switch (exceptionInfo.ExceptionRecord.ExceptionCode) switch (exceptionInfo.ExceptionRecord.ExceptionCode)
@ -55,8 +81,5 @@ namespace GleeBug
//call the unhandled exception callback //call the unhandled exception callback
if (_continueStatus == DBG_EXCEPTION_NOT_HANDLED) if (_continueStatus == DBG_EXCEPTION_NOT_HANDLED)
cbUnhandledException(exceptionRecord, firstChance); cbUnhandledException(exceptionRecord, firstChance);
//call the debug event callback
cbExceptionEvent(exceptionInfo);
} }
}; };

View File

@ -0,0 +1,54 @@
#include "Debugger.Process.h"
namespace GleeBug
{
bool ProcessInfo::SetBreakpoint(ptr address, bool singleshoot, SoftwareBreakpointType type)
{
//check the address
if (!MemIsValidPtr(address) ||
breakpoints.find({BreakpointType::Software, address}) != breakpoints.end())
return false;
//setup the breakpoint information struct
BreakpointInfo info = {};
info.address = address;
info.enabled = true;
info.singleshoot = singleshoot;
info.type = BreakpointType::Software;
//determine breakpoint byte and size from the type
switch (type)
{
case SoftwareBreakpointType::ShortInt3:
info.internal.software.newbytes[0] = 0xCC;
info.internal.software.size = 1;
break;
default:
return false;
}
//read/write the breakpoint
if (!MemRead(address, info.internal.software.oldbytes, info.internal.software.size))
return false;
if (!MemWrite(address, info.internal.software.newbytes, info.internal.software.size))
return false;
//insert in the breakpoint map
breakpoints.insert({ { info.type, info.address }, info });
return true;
}
bool ProcessInfo::SetBreakpoint(ptr address, const BreakpointCallback & cbBreakpoint, bool singleshoot, SoftwareBreakpointType type)
{
if (!SetBreakpoint(address, singleshoot, type))
return false;
auto found = breakpointCallbacks.find({ BreakpointType::Software, address });
if (found != breakpointCallbacks.end())
return false;
breakpointCallbacks.insert({ { BreakpointType::Software, address }, cbBreakpoint });
return true;
}
};

View File

@ -0,0 +1,20 @@
#include "Debugger.Process.h"
namespace GleeBug
{
bool ProcessInfo::MemRead(ptr address, void* buffer, ptr size) const
{
return !!ReadProcessMemory(this->hProcess, reinterpret_cast<const void*>(address), buffer, size, nullptr);
}
bool ProcessInfo::MemWrite(ptr address, const void* buffer, ptr size)
{
return !!WriteProcessMemory(this->hProcess, reinterpret_cast<void*>(address), buffer, size, nullptr);
}
bool ProcessInfo::MemIsValidPtr(ptr address) const
{
uint8 byte;
return MemRead(address, &byte, sizeof(byte));
}
};

View File

@ -9,14 +9,4 @@ namespace GleeBug
this->dwProcessId = dwProcessId; this->dwProcessId = dwProcessId;
this->dwMainThreadId = dwMainThreadId; this->dwMainThreadId = dwMainThreadId;
} }
bool ProcessInfo::MemRead(ptr address, void* buffer, const size_t size) const
{
return !!ReadProcessMemory(this->hProcess, reinterpret_cast<const void*>(address), buffer, size, nullptr);
}
bool ProcessInfo::MemWrite(ptr address, const void* buffer, const size_t size) const
{
return !!WriteProcessMemory(this->hProcess, reinterpret_cast<void*>(address), buffer, size, nullptr);
}
}; };

View File

@ -4,6 +4,7 @@
#include "Debugger.Global.h" #include "Debugger.Global.h"
#include "Debugger.Thread.h" #include "Debugger.Thread.h"
#include "Debugger.Dll.h" #include "Debugger.Dll.h"
#include "Debugger.Breakpoint.h"
namespace GleeBug namespace GleeBug
{ {
@ -22,6 +23,8 @@ namespace GleeBug
ThreadMap threads; ThreadMap threads;
DllMap dlls; DllMap dlls;
BreakpointMap breakpoints;
BreakpointCallbackMap breakpointCallbacks;
/** /**
\brief Constructor. \brief Constructor.
@ -37,7 +40,7 @@ namespace GleeBug
\param size The size to read. \param size The size to read.
\return true if it succeeds, false if it fails. \return true if it succeeds, false if it fails.
*/ */
bool MemRead(ptr address, void* buffer, const size_t size) const; bool MemRead(ptr address, void* buffer, ptr size) const;
/** /**
\brief Write memory to the process. \brief Write memory to the process.
@ -46,7 +49,50 @@ namespace GleeBug
\param size The size to write. \param size The size to write.
\return true if it succeeds, false if it fails. \return true if it succeeds, false if it fails.
*/ */
bool MemWrite(ptr address, const void* buffer, const size_t size) const; bool MemWrite(ptr address, const void* buffer, ptr size);
/**
\brief Check if an address is a valid read pointer.
\param address The address to check.
\return true if the address is valid, false otherwise.
*/
bool MemIsValidPtr(ptr address) const;
/**
\brief Sets a software breakpoint.
\param address The address to put the breakpoint on.
\param singleshoot (Optional) True to remove the breakpoint after the first hit.
\param type (Optional) The software breakpoint type.
\return true if the breakpoint was set, false otherwise.
*/
bool SetBreakpoint(ptr address, bool singleshoot = false, SoftwareBreakpointType type = SoftwareBreakpointType::ShortInt3);
/**
\brief Sets a software breakpoint.
\param address The address to put the breakpoint on.
\param cbBreakpoint The breakpoint callback. Can be written using BIND1(this, MyDebugger::cb).
\param singleshoot (Optional) True to remove the breakpoint after the first hit.
\param type (Optional) The software breakpoint type.
\return true if the breakpoint was set, false otherwise.
*/
bool SetBreakpoint(ptr address, const BreakpointCallback & cbBreakpoint, bool singleshoot = false, SoftwareBreakpointType type = SoftwareBreakpointType::ShortInt3);
/**
\brief Sets a software breakpoint.
\tparam T Generic type parameter. Must be a subclass of Debugger.
\param address The address to put the breakpoint on.
\param debugger This pointer to a subclass of Debugger.
\param callback Pointer to the callback. Written like: &MyDebugger::cb
\param singleshoot (Optional) True to remove the breakpoint after the first hit.
\param type (Optional) The software breakpoint type.
\return true if the breakpoint was set, false otherwise.
*/
template <typename T>
bool SetBreakpoint(ptr address, T* debugger, void(T::*callback)(const BreakpointInfo & info), bool singleshoot = false, SoftwareBreakpointType type = SoftwareBreakpointType::ShortInt3)
{
static_cast<void>(static_cast<Debugger*>(debugger));
return SetBreakpoint(address, std::bind(callback, debugger, std::placeholders::_1), singleshoot, type);
}
}; };
}; };

View File

@ -3,6 +3,7 @@
#include "Debugger.Global.h" #include "Debugger.Global.h"
#include "Debugger.Process.h" #include "Debugger.Process.h"
#include "Debugger.Breakpoint.h"
namespace GleeBug namespace GleeBug
{ {
@ -52,55 +53,55 @@ namespace GleeBug
protected: //debug event callbacks protected: //debug event callbacks
/** /**
\brief Process creation debug event callback. Provide an implementation to use this callback. \brief Process creation debug event callback. Called after the event is internally processed. Provide an implementation to use this callback.
\param createProcess Information about the process created. \param createProcess Information about the process created.
*/ */
virtual void cbCreateProcessEvent(const CREATE_PROCESS_DEBUG_INFO & createProcess, const ProcessInfo & process) {}; virtual void cbCreateProcessEvent(const CREATE_PROCESS_DEBUG_INFO & createProcess, const ProcessInfo & process) {};
/** /**
\brief Process termination debug event callback. Provide an implementation to use this callback. \brief Process termination debug event callback. Called before the event is internally processed. Provide an implementation to use this callback.
\param exitProcess Information about the process terminated. \param exitProcess Information about the process terminated.
*/ */
virtual void cbExitProcessEvent(const EXIT_PROCESS_DEBUG_INFO & exitProcess, const ProcessInfo & process) {}; virtual void cbExitProcessEvent(const EXIT_PROCESS_DEBUG_INFO & exitProcess, const ProcessInfo & process) {};
/** /**
\brief Thread creation debug event callback. Provide an implementation to use this callback. \brief Thread creation debug event callback. Called after the event is internally processed. Provide an implementation to use this callback.
\param createThread Information about the thread created. \param createThread Information about the thread created.
*/ */
virtual void cbCreateThreadEvent(const CREATE_THREAD_DEBUG_INFO & createThread, const ThreadInfo & thread) {}; virtual void cbCreateThreadEvent(const CREATE_THREAD_DEBUG_INFO & createThread, const ThreadInfo & thread) {};
/** /**
\brief Thread termination debug event callback. Provide an implementation to use this callback. \brief Thread termination debug event callback. Called before the event is internally processed. Provide an implementation to use this callback.
\param exitThread Information about the thread terminated. \param exitThread Information about the thread terminated.
*/ */
virtual void cbExitThreadEvent(const EXIT_THREAD_DEBUG_INFO & exitThread, const ThreadInfo & thread) {}; virtual void cbExitThreadEvent(const EXIT_THREAD_DEBUG_INFO & exitThread, const ThreadInfo & thread) {};
/** /**
\brief DLL load debug event callback. Provide an implementation to use this callback. \brief DLL load debug event callback. Called after event is internally processed. Provide an implementation to use this callback.
\param loadDll Information about the DLL loaded. \param loadDll Information about the DLL loaded.
*/ */
virtual void cbLoadDllEvent(const LOAD_DLL_DEBUG_INFO & loadDll, const DllInfo & dll) {}; virtual void cbLoadDllEvent(const LOAD_DLL_DEBUG_INFO & loadDll, const DllInfo & dll) {};
/** /**
\brief DLL unload debug event callback. Provide an implementation to use this callback. \brief DLL unload debug event callback. Called before event is internally processed. Provide an implementation to use this callback.
\param unloadDll Information about the DLL unloaded. \param unloadDll Information about the DLL unloaded.
*/ */
virtual void cbUnloadDllEvent(const UNLOAD_DLL_DEBUG_INFO & unloadDll, const DllInfo & dll) {}; virtual void cbUnloadDllEvent(const UNLOAD_DLL_DEBUG_INFO & unloadDll, const DllInfo & dll) {};
/** /**
\brief Exception debug event callback. Provide an implementation to use this callback. \brief Exception debug event callback. Called before the event is internally processed. Provide an implementation to use this callback.
\param exceptionInfo Information about the exception. \param exceptionInfo Information about the exception.
*/ */
virtual void cbExceptionEvent(const EXCEPTION_DEBUG_INFO & exceptionInfo) {}; virtual void cbExceptionEvent(const EXCEPTION_DEBUG_INFO & exceptionInfo) {};
/** /**
\brief Debug string debug event callback. Provide an implementation to use this callback. \brief Debug string debug event callback. Called before the event is internally processed. Provide an implementation to use this callback.
\param debugString Information about the debug string. \param debugString Information about the debug string.
*/ */
virtual void cbDebugStringEvent(const OUTPUT_DEBUG_STRING_INFO & debugString) {}; virtual void cbDebugStringEvent(const OUTPUT_DEBUG_STRING_INFO & debugString) {};
/** /**
\brief RIP debug event callback. Provide an implementation to use this callback. \brief RIP debug event callback. Called before the event is internally processed. Provide an implementation to use this callback.
\param rip Information about the RIP event. \param rip Information about the RIP event.
*/ */
virtual void cbRipEvent(const RIP_INFO & rip) {}; virtual void cbRipEvent(const RIP_INFO & rip) {};
@ -113,22 +114,28 @@ namespace GleeBug
virtual void cbInternalError(const std::string & error) {}; virtual void cbInternalError(const std::string & error) {};
/** /**
\brief Unhandled exception callback. Provide an implementation to use this callback. \brief Unhandled exception callback. Called after the exception event is processed. Provide an implementation to use this callback.
\param exceptionRecord The exception record. \param exceptionRecord The exception record.
\param firstChance True if the exception is a first chance exception, false otherwise. \param firstChance True if the exception is a first chance exception, false otherwise.
*/ */
virtual void cbUnhandledException(const EXCEPTION_RECORD & exceptionRecord, const bool firstChance) {}; virtual void cbUnhandledException(const EXCEPTION_RECORD & exceptionRecord, bool firstChance) {};
/** /**
\brief System breakpoint callback. Provide an implementation to use this callback. \brief System breakpoint callback. Called after the event is internally processed. Provide an implementation to use this callback.
*/ */
virtual void cbSystemBreakpoint() {}; virtual void cbSystemBreakpoint() {};
/** /**
\brief Step callback. Provide an implementation to use this callback. \brief Step callback. Called before any user callbacks. Provide an implementation to use this callback.
*/ */
virtual void cbStep() {}; virtual void cbStep() {};
/**
\brief Breakpoint callback. Called before any user callbacks. Provide an implementation to use this callback.
\param info The breakpoint information.
*/
virtual void cbBreakpoint(const BreakpointInfo & info) {}
protected: //core debug event handlers protected: //core debug event handlers
/** /**
\brief Process creation debug event. Do not override this unless you know what you are doing! \brief Process creation debug event. Do not override this unless you know what you are doing!
@ -190,14 +197,14 @@ namespace GleeBug
\param exceptionRecord The exception record. \param exceptionRecord The exception record.
\param firstChance True if the exception is a first chance exception, false otherwise. \param firstChance True if the exception is a first chance exception, false otherwise.
*/ */
virtual void exceptionBreakpoint(const EXCEPTION_RECORD & exceptionRecord, const bool firstChance); virtual void exceptionBreakpoint(const EXCEPTION_RECORD & exceptionRecord, bool firstChance);
/** /**
\brief Single step exception handler. Do not override this unless you know what you are doing! \brief Single step exception handler. Do not override this unless you know what you are doing!
\param exceptionRecord The exception record. \param exceptionRecord The exception record.
\param firstChance True if the exception is a first chance exception, false otherwise. \param firstChance True if the exception is a first chance exception, false otherwise.
*/ */
virtual void exceptionSingleStep(const EXCEPTION_RECORD & exceptionRecord, const bool firstChance); virtual void exceptionSingleStep(const EXCEPTION_RECORD & exceptionRecord, bool firstChance);
protected: //variables protected: //variables
PROCESS_INFORMATION _mainProcess; PROCESS_INFORMATION _mainProcess;

View File

@ -15,6 +15,7 @@
//macros //macros
#define BIND(thisPtr, funcPtr) std::bind(&funcPtr, thisPtr) #define BIND(thisPtr, funcPtr) std::bind(&funcPtr, thisPtr)
#define BIND1(thisPtr, funcPtr) std::bind(&funcPtr, thisPtr, std::placeholders::_1)
namespace GleeBug namespace GleeBug
{ {

View File

@ -155,12 +155,15 @@
<ClCompile Include="Debugger.Loop.Process.cpp" /> <ClCompile Include="Debugger.Loop.Process.cpp" />
<ClCompile Include="Debugger.Loop.Rip.cpp" /> <ClCompile Include="Debugger.Loop.Rip.cpp" />
<ClCompile Include="Debugger.Loop.Thread.cpp" /> <ClCompile Include="Debugger.Loop.Thread.cpp" />
<ClCompile Include="Debugger.Process.Breakpoint.cpp" />
<ClCompile Include="Debugger.Process.cpp" /> <ClCompile Include="Debugger.Process.cpp" />
<ClCompile Include="Debugger.Process.Memory.cpp" />
<ClCompile Include="Debugger.Thread.cpp" /> <ClCompile Include="Debugger.Thread.cpp" />
<ClCompile Include="Debugger.Thread.Registers.cpp" /> <ClCompile Include="Debugger.Thread.Registers.cpp" />
<ClCompile Include="Debugger.Thread.Registers.GetSet.cpp" /> <ClCompile Include="Debugger.Thread.Registers.GetSet.cpp" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClInclude Include="Debugger.Breakpoint.h" />
<ClInclude Include="Debugger.Dll.h" /> <ClInclude Include="Debugger.Dll.h" />
<ClInclude Include="Debugger.Process.h" /> <ClInclude Include="Debugger.Process.h" />
<ClInclude Include="Debugger.h" /> <ClInclude Include="Debugger.h" />

View File

@ -50,6 +50,12 @@
<ClCompile Include="Debugger.Thread.Registers.GetSet.cpp"> <ClCompile Include="Debugger.Thread.Registers.GetSet.cpp">
<Filter>Source Files</Filter> <Filter>Source Files</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="Debugger.Process.Memory.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Debugger.Process.Breakpoint.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClInclude Include="Debugger.h"> <ClInclude Include="Debugger.h">
@ -79,5 +85,8 @@
<ClInclude Include="Debugger.Thread.Registers.Flag.h"> <ClInclude Include="Debugger.Thread.Registers.Flag.h">
<Filter>Header Files</Filter> <Filter>Header Files</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="Debugger.Breakpoint.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup> </ItemGroup>
</Project> </Project>

View File

@ -8,11 +8,21 @@ using namespace GleeBug;
class MyDebugger : public Debugger class MyDebugger : public Debugger
{ {
protected: protected:
void myBreakpoint(const BreakpointInfo & info)
{
puts("myBreakpoint()");
}
void cbCreateProcessEvent(const CREATE_PROCESS_DEBUG_INFO & createProcess, const ProcessInfo & process) override void cbCreateProcessEvent(const CREATE_PROCESS_DEBUG_INFO & createProcess, const ProcessInfo & process) override
{ {
ptr entry = ptr(createProcess.lpStartAddress);
printf("Process %d created with entry 0x%p\n", printf("Process %d created with entry 0x%p\n",
_debugEvent.dwProcessId, _debugEvent.dwProcessId,
createProcess.lpStartAddress); entry);
if(_process->SetBreakpoint(entry, this, &MyDebugger::myBreakpoint))
printf("Breakpoint set at 0x%p!\n", entry);
else
printf("Failed to set breakpoint at 0x%p...\b", entry);
} }
void cbExitProcessEvent(const EXIT_PROCESS_DEBUG_INFO & exitProcess, const ProcessInfo & process) override void cbExitProcessEvent(const EXIT_PROCESS_DEBUG_INFO & exitProcess, const ProcessInfo & process) override
@ -50,7 +60,9 @@ protected:
void cbExceptionEvent(const EXCEPTION_DEBUG_INFO & exceptionInfo) override void cbExceptionEvent(const EXCEPTION_DEBUG_INFO & exceptionInfo) override
{ {
printf("Exception with code 0x%08X at 0x%p\n", const char* exceptionType = exceptionInfo.dwFirstChance ? "First Chance" : "Second Chance";
printf("%s exception with code 0x%08X at 0x%p\n",
exceptionType,
exceptionInfo.ExceptionRecord.ExceptionCode, exceptionInfo.ExceptionRecord.ExceptionCode,
exceptionInfo.ExceptionRecord.ExceptionAddress); exceptionInfo.ExceptionRecord.ExceptionAddress);
} }
@ -87,7 +99,7 @@ protected:
{ {
printf("System breakpoint reached, CIP: 0x%p\n", printf("System breakpoint reached, CIP: 0x%p\n",
_registers->Gip.Get()); _registers->Gip.Get());
_thread->StepInto(BIND(this, MyDebugger::boobs)); _thread->StepInto(this, &MyDebugger::boobs);
} }
void cbInternalError(const std::string & error) override void cbInternalError(const std::string & error) override
@ -95,6 +107,12 @@ protected:
printf("Internal Error: %s\n", printf("Internal Error: %s\n",
error.c_str()); error.c_str());
} }
void cbBreakpoint(const BreakpointInfo & info) override
{
printf("Breakpoint on 0x%p!\n",
info.address);
}
}; };
#endif //_MYDEBUGGER_H #endif //_MYDEBUGGER_H