remove lazy context

This commit is contained in:
mrexodia 2017-06-04 18:26:42 +02:00
parent 22c5c2189c
commit 0b18c04e1e
No known key found for this signature in database
GPG Key ID: FC89E0AAA0C1AAD8
11 changed files with 113 additions and 74 deletions

View File

@ -2,6 +2,7 @@
#define DEBUGGER_GLOBAL_H
#include "GleeBug.h"
#include <memory>
//defines
#define GLEEBUG_HWBP_COUNT 4
@ -30,9 +31,9 @@ namespace GleeBug
typedef std::function<void(const BreakpointInfo & info)> BreakpointCallback;
//map typedefs
typedef std::map<uint32, Process> ProcessMap;
typedef std::map<uint32, std::unique_ptr<Process>> ProcessMap;
typedef std::map<Range, Dll, RangeCompare> DllMap;
typedef std::map<uint32, Thread> ThreadMap;
typedef std::map<uint32, std::unique_ptr<Thread>> ThreadMap;
typedef std::map<BreakpointKey, BreakpointInfo> BreakpointMap;
typedef std::map<BreakpointKey, BreakpointCallback> BreakpointCallbackMap;
typedef std::unordered_map<ptr, BreakpointMap::iterator> SoftwareBreakpointMap;

View File

@ -16,19 +16,19 @@ namespace GleeBug
//process housekeeping
mProcesses.insert({ mDebugEvent.dwProcessId,
Process(createProcess.hProcess,
std::make_unique<Process>(createProcess.hProcess,
mDebugEvent.dwProcessId,
mDebugEvent.dwThreadId,
createProcess) });
mProcess = &mProcesses.find(mDebugEvent.dwProcessId)->second;
mProcess = mProcesses.find(mDebugEvent.dwProcessId)->second.get();
//thread housekeeping (main thread is created implicitly)
mProcess->threads.insert({ mDebugEvent.dwThreadId,
Thread(createProcess.hThread,
std::make_unique<Thread>(createProcess.hThread,
mDebugEvent.dwThreadId,
createProcess.lpThreadLocalBase,
createProcess.lpStartAddress) });
mThread = mProcess->thread = &mProcess->threads.find(mDebugEvent.dwThreadId)->second;
mThread = mProcess->thread = mProcess->threads.find(mDebugEvent.dwThreadId)->second.get();
mRegisters = &mThread->registers;
//read thread context from main thread

View File

@ -6,13 +6,13 @@ namespace GleeBug
{
//thread housekeeping
mProcess->threads.insert({ mDebugEvent.dwThreadId,
Thread(createThread.hThread,
std::make_unique<Thread>(createThread.hThread,
mDebugEvent.dwThreadId,
createThread.lpThreadLocalBase,
createThread.lpStartAddress) });
//set the current thread
mThread = mProcess->thread = &mProcess->threads.find(mDebugEvent.dwThreadId)->second;
mThread = mProcess->thread = mProcess->threads.find(mDebugEvent.dwThreadId)->second.get();
mRegisters = &mThread->registers;
if (!mThread->RegReadContext())
cbInternalError("Thread::RegReadContext() failed!");

View File

@ -38,11 +38,11 @@ namespace GleeBug
auto processFound = mProcesses.find(mDebugEvent.dwProcessId);
if (processFound != mProcesses.end())
{
mProcess = &processFound->second;
mProcess = processFound->second.get();
auto threadFound = mProcess->threads.find(mDebugEvent.dwThreadId);
if (threadFound != mProcess->threads.end())
{
mThread = mProcess->thread = &threadFound->second;
mThread = mProcess->thread = threadFound->second.get();
mRegisters = &mThread->registers;
}
else

View File

@ -100,7 +100,7 @@ namespace GleeBug
bool success = true;
for (auto & thread : threads)
{
if (!thread.second.SetHardwareBreakpoint(address, slot, type, size))
if (!thread.second->SetHardwareBreakpoint(address, slot, type, size))
{
success = false;
break;
@ -111,7 +111,7 @@ namespace GleeBug
if (!success)
{
for (auto & thread : threads)
thread.second.DeleteHardwareBreakpoint(slot);
thread.second->DeleteHardwareBreakpoint(slot);
return false;
}
@ -161,7 +161,7 @@ namespace GleeBug
bool success = true;
for (auto & thread : threads)
{
if (!thread.second.DeleteHardwareBreakpoint(info.internal.hardware.slot))
if (!thread.second->DeleteHardwareBreakpoint(info.internal.hardware.slot))
success = false;
}

View File

@ -24,7 +24,7 @@ namespace GleeBug
bool systemBreakpoint;
bool permanentDep;
ThreadMap threads; //DO NOT COPY THESE OBJECTS!
ThreadMap threads;
DllMap dlls;
BreakpointMap breakpoints;
SoftwareBreakpointMap softwareBreakpointReferences;
@ -42,6 +42,11 @@ namespace GleeBug
*/
explicit Process(HANDLE hProcess, uint32 dwProcessId, uint32 dwMainThreadId, const CREATE_PROCESS_DEBUG_INFO & createProcessInfo);
/**
\brief Copy constructor.
*/
Process(const Process &) = delete;
/**
\brief Read memory from the process.
\param address The virtual address to read from.
@ -397,7 +402,7 @@ namespace GleeBug
{
auto result = true;
for(auto & thread : this->threads)
if(!thread.second.RegReadContext())
if(!thread.second->RegReadContext())
result = false;
return result;
}
@ -406,7 +411,7 @@ namespace GleeBug
{
auto result = true;
for(auto & thread : this->threads)
if(!thread.second.RegWriteContext())
if(!thread.second->RegWriteContext())
result = false;
return result;
}

View File

@ -19,6 +19,11 @@ namespace GleeBug
*/
Registers();
/**
\brief Copy constructor.
*/
Registers(const Registers &) = delete;
#include "Debugger.Thread.Registers.Register.h"
Register<R::DR0, ptr> Dr0;

View File

@ -13,39 +13,17 @@ namespace GleeBug
{
}
Thread::Thread(const Thread & other) :
hThread(other.hThread),
dwThreadId(other.dwThreadId),
lpThreadLocalBase(other.lpThreadLocalBase),
lpStartAddress(other.lpStartAddress),
registers(), //create new registers
stepCallbacks(other.stepCallbacks),
isSingleStepping(other.isSingleStepping),
isInternalStepping(other.isInternalStepping),
cbInternalStep(other.cbInternalStep)
{
}
Thread & Thread::operator=(const Thread& other)
{
hThread = other.hThread;
dwThreadId = other.dwThreadId;
lpThreadLocalBase = other.lpThreadLocalBase;
lpStartAddress = other.lpStartAddress;
registers = Registers(); //create new registers
stepCallbacks = other.stepCallbacks;
isSingleStepping = other.isSingleStepping;
isInternalStepping = other.isInternalStepping;
cbInternalStep = other.cbInternalStep;
return *this;
}
bool Thread::RegReadContext()
{
memset(&this->mOldContext, 0, sizeof(CONTEXT));
this->mOldContext.ContextFlags = CONTEXT_ALL; //TODO: granular control over what's required
this->registers.setContextLazy(&this->mOldContext, this->hThread);
return true;
if(GetThreadContext(this->hThread, &this->mOldContext))
{
this->registers.SetContext(this->mOldContext);
return true;
}
__debugbreak();
return false;
}
bool Thread::RegWriteContext()
@ -54,7 +32,10 @@ namespace GleeBug
if (memcmp(&this->mOldContext, &this->registers.mContext, sizeof(CONTEXT)) == 0)
return true;
//update the context
return !!SetThreadContext(this->hThread, &this->registers.mContext);
if(SetThreadContext(this->hThread, &this->registers.mContext))
return true;
__debugbreak();
return false;
}
void Thread::StepInto()
@ -85,4 +66,14 @@ namespace GleeBug
isInternalStepping = true;
cbInternalStep = cbStep;
}
bool Thread::Suspend()
{
return SuspendThread(hThread) != -1;
}
bool Thread::Resume()
{
return ResumeThread(hThread) != -1;
}
};

View File

@ -36,14 +36,7 @@ namespace GleeBug
/**
\brief Copy constructor.
*/
Thread(const Thread & other);
/**
\brief Assignment operator.
\param other The other object.
\return A shallow copy of this object.
*/
Thread & operator=(const Thread & other);
Thread(const Thread & other) = delete;
/**
\brief Read the register context from the thread. This fills the RegistersInfo member.
@ -117,6 +110,18 @@ namespace GleeBug
*/
bool DeleteHardwareBreakpoint(HardwareSlot slot);
/**
\brief Suspends this thread.
\return true if it succeeds, false if it fails.
*/
bool Suspend();
/**
\brief Resumes this thread.
\return true if it succeeds, false if it fails.
*/
bool Resume();
private:
CONTEXT mOldContext;
};

View File

@ -18,6 +18,11 @@ namespace GleeBug
*/
Debugger();
/**
\brief Copy constructor.
*/
Debugger(const Debugger &) = delete;
/**
\brief Destructs the Debugger instance.
*/

View File

@ -240,6 +240,32 @@ public:
mThread->StepInto(STEPCALLBACK(CallBack));
}
struct ThreadSuspender
{
ThreadSuspender(Thread* thread, bool running, bool writeRegs)
: thread(running ? thread : nullptr), writeRegs(writeRegs)
{
if(this->thread)
{
this->thread->Suspend();
this->thread->RegReadContext();
}
}
~ThreadSuspender()
{
if(this->thread)
{
if(this->writeRegs)
this->thread->RegWriteContext();
this->thread->Resume();
}
}
Thread* thread;
bool writeRegs;
};
//Registers
ULONG_PTR GetContextDataEx(HANDLE hActiveThread, DWORD IndexOfRegister)
{
@ -248,8 +274,7 @@ public:
auto thread = threadFromHandle(hActiveThread);
if(!thread)
return 0;
if(mIsRunning)
thread->RegReadContext();
ThreadSuspender suspender(thread, mIsRunning, false);
return thread->registers.Get(registerFromDword(IndexOfRegister));
}
@ -258,11 +283,8 @@ public:
auto thread = threadFromHandle(hActiveThread);
if (!thread)
return false;
if(mIsRunning)
thread->RegReadContext();
ThreadSuspender suspender(thread, mIsRunning, true);
thread->registers.Set(registerFromDword(IndexOfRegister), NewRegisterValue);
if(mIsRunning)
thread->RegWriteContext();
return true;
}
@ -273,8 +295,7 @@ public:
auto thread = threadFromHandle(hActiveThread);
if (!thread || !titcontext)
return false;
if(mIsRunning)
thread->RegReadContext();
ThreadSuspender suspender(thread, mIsRunning, false);
memset(titcontext, 0, sizeof(TITAN_ENGINE_CONTEXT_t));
auto context = thread->registers.GetContext();
titcontext->cax = thread->registers.Gax();
@ -317,8 +338,7 @@ public:
auto thread = threadFromHandle(hActiveThread);
if (!thread || !titcontext)
return false;
if(mIsRunning)
thread->RegReadContext();
ThreadSuspender suspender(thread, mIsRunning, true);
thread->registers.Gax = titcontext->cax;
thread->registers.Gcx = titcontext->ccx;
thread->registers.Gdx = titcontext->cdx;
@ -353,8 +373,6 @@ public:
context.SegCs = titcontext->cs;
context.SegSs = titcontext->ss;
thread->registers.SetContext(context);
if(mIsRunning)
thread->RegWriteContext();
return true;
}
@ -572,16 +590,25 @@ public:
{
if (!mProcess)
return false;
if(mIsRunning)
auto running = mIsRunning;
if(running)
{
for(auto & thread : mProcess->threads)
thread.second->Suspend();
mProcess->RegReadContext();
}
if(!mProcess->SetHardwareBreakpoint(bpxAddress,
(HardwareSlot)IndexOfRegister, [bpxCallBack](const BreakpointInfo & info)
{
(HWBPCALLBACK(bpxCallBack))((const void*)info.address);
}, hwtypeFromTitan(bpxType), hwsizeFromTitan(bpxSize)))
return false;
if(mIsRunning)
if(running)
{
mProcess->RegWriteContext();
for(auto & thread : mProcess->threads)
thread.second->Resume();
}
return true;
}
@ -622,9 +649,9 @@ public:
{
for(auto & it : mProcesses)
{
auto breakpoints = it.second.breakpoints; //explicit copy
auto breakpoints = it.second->breakpoints; //explicit copy
for(const auto & jt : breakpoints)
it.second.DeleteGenericBreakpoint(jt.second);
it.second->DeleteGenericBreakpoint(jt.second);
}
return false;
}
@ -756,10 +783,10 @@ private: //functions
auto foundP = mProcesses.find(uint32(tbi.ClientId.UniqueProcess));
if(foundP == mProcesses.end())
return nullptr;
auto foundT = foundP->second.threads.find(uint32(tbi.ClientId.UniqueThread));
if(foundT == foundP->second.threads.end())
auto foundT = foundP->second->threads.find(uint32(tbi.ClientId.UniqueThread));
if(foundT == foundP->second->threads.end())
return nullptr;
return &foundT->second;
return foundT->second.get();
}
Process* processFromHandle(HANDLE hProcess)
@ -767,7 +794,7 @@ private: //functions
auto foundP = mProcesses.find(GetProcessId(hProcess));
if(foundP == mProcesses.end())
return nullptr;
return &foundP->second;
return foundP->second.get();
}
static HardwareType hwtypeFromTitan(DWORD type)