From 0b18c04e1e26084cd4b90575761c525bdcca1f7c Mon Sep 17 00:00:00 2001 From: mrexodia Date: Sun, 4 Jun 2017 18:26:42 +0200 Subject: [PATCH] remove lazy context --- GleeBug/Debugger.Global.h | 5 +- GleeBug/Debugger.Loop.Process.cpp | 8 +-- GleeBug/Debugger.Loop.Thread.cpp | 4 +- GleeBug/Debugger.Loop.cpp | 4 +- GleeBug/Debugger.Process.Breakpoint.cpp | 6 +-- GleeBug/Debugger.Process.h | 11 ++-- GleeBug/Debugger.Thread.Registers.h | 5 ++ GleeBug/Debugger.Thread.cpp | 51 ++++++++----------- GleeBug/Debugger.Thread.h | 21 +++++--- GleeBug/Debugger.h | 5 ++ TitanEngineEmulator/Emulator.h | 67 +++++++++++++++++-------- 11 files changed, 113 insertions(+), 74 deletions(-) diff --git a/GleeBug/Debugger.Global.h b/GleeBug/Debugger.Global.h index c3345c6..3ffc3e3 100644 --- a/GleeBug/Debugger.Global.h +++ b/GleeBug/Debugger.Global.h @@ -2,6 +2,7 @@ #define DEBUGGER_GLOBAL_H #include "GleeBug.h" +#include //defines #define GLEEBUG_HWBP_COUNT 4 @@ -30,9 +31,9 @@ namespace GleeBug typedef std::function BreakpointCallback; //map typedefs - typedef std::map ProcessMap; + typedef std::map> ProcessMap; typedef std::map DllMap; - typedef std::map ThreadMap; + typedef std::map> ThreadMap; typedef std::map BreakpointMap; typedef std::map BreakpointCallbackMap; typedef std::unordered_map SoftwareBreakpointMap; diff --git a/GleeBug/Debugger.Loop.Process.cpp b/GleeBug/Debugger.Loop.Process.cpp index d1ede6d..5690828 100644 --- a/GleeBug/Debugger.Loop.Process.cpp +++ b/GleeBug/Debugger.Loop.Process.cpp @@ -16,19 +16,19 @@ namespace GleeBug //process housekeeping mProcesses.insert({ mDebugEvent.dwProcessId, - Process(createProcess.hProcess, + std::make_unique(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(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 diff --git a/GleeBug/Debugger.Loop.Thread.cpp b/GleeBug/Debugger.Loop.Thread.cpp index 6344107..7c6f9ec 100644 --- a/GleeBug/Debugger.Loop.Thread.cpp +++ b/GleeBug/Debugger.Loop.Thread.cpp @@ -6,13 +6,13 @@ namespace GleeBug { //thread housekeeping mProcess->threads.insert({ mDebugEvent.dwThreadId, - Thread(createThread.hThread, + std::make_unique(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!"); diff --git a/GleeBug/Debugger.Loop.cpp b/GleeBug/Debugger.Loop.cpp index 7a68b9d..863e11e 100644 --- a/GleeBug/Debugger.Loop.cpp +++ b/GleeBug/Debugger.Loop.cpp @@ -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 diff --git a/GleeBug/Debugger.Process.Breakpoint.cpp b/GleeBug/Debugger.Process.Breakpoint.cpp index 0bab2dc..6e3bb72 100644 --- a/GleeBug/Debugger.Process.Breakpoint.cpp +++ b/GleeBug/Debugger.Process.Breakpoint.cpp @@ -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; } diff --git a/GleeBug/Debugger.Process.h b/GleeBug/Debugger.Process.h index 0ff8d7a..2321247 100644 --- a/GleeBug/Debugger.Process.h +++ b/GleeBug/Debugger.Process.h @@ -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; } diff --git a/GleeBug/Debugger.Thread.Registers.h b/GleeBug/Debugger.Thread.Registers.h index 547faa8..62f571d 100644 --- a/GleeBug/Debugger.Thread.Registers.h +++ b/GleeBug/Debugger.Thread.Registers.h @@ -19,6 +19,11 @@ namespace GleeBug */ Registers(); + /** + \brief Copy constructor. + */ + Registers(const Registers &) = delete; + #include "Debugger.Thread.Registers.Register.h" Register Dr0; diff --git a/GleeBug/Debugger.Thread.cpp b/GleeBug/Debugger.Thread.cpp index 509c7b6..ccadad7 100644 --- a/GleeBug/Debugger.Thread.cpp +++ b/GleeBug/Debugger.Thread.cpp @@ -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; + } }; \ No newline at end of file diff --git a/GleeBug/Debugger.Thread.h b/GleeBug/Debugger.Thread.h index 68bcb71..c45e0fb 100644 --- a/GleeBug/Debugger.Thread.h +++ b/GleeBug/Debugger.Thread.h @@ -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; }; diff --git a/GleeBug/Debugger.h b/GleeBug/Debugger.h index 2b9b30d..4088115 100644 --- a/GleeBug/Debugger.h +++ b/GleeBug/Debugger.h @@ -18,6 +18,11 @@ namespace GleeBug */ Debugger(); + /** + \brief Copy constructor. + */ + Debugger(const Debugger &) = delete; + /** \brief Destructs the Debugger instance. */ diff --git a/TitanEngineEmulator/Emulator.h b/TitanEngineEmulator/Emulator.h index b46d152..7a0e289 100644 --- a/TitanEngineEmulator/Emulator.h +++ b/TitanEngineEmulator/Emulator.h @@ -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)