diff --git a/GleeBug/Debugger.Thread.Registers.cpp b/GleeBug/Debugger.Thread.Registers.cpp index a73f290..fd92910 100644 --- a/GleeBug/Debugger.Thread.Registers.cpp +++ b/GleeBug/Debugger.Thread.Registers.cpp @@ -107,12 +107,13 @@ namespace GleeBug ResumeFlag(this) { memset(&this->mContext, 0, sizeof(CONTEXT)); + InitializeCriticalSection(&mCr); } - CONTEXT* Registers::GetContext() + LockedPtr Registers::GetContext() { handleLazyContext(); - return &mContext; + return LockedPtr(&mCr, &mContext); } /*void Registers::SetContext(const CONTEXT & context) @@ -130,6 +131,8 @@ namespace GleeBug bool Registers::handleLazyContext() { + ScopedCriticalSection lock(&mCr); + if(!this->mLazySet) return true; diff --git a/GleeBug/Debugger.Thread.Registers.h b/GleeBug/Debugger.Thread.Registers.h index 9eebad1..ca9a7c3 100644 --- a/GleeBug/Debugger.Thread.Registers.h +++ b/GleeBug/Debugger.Thread.Registers.h @@ -5,6 +5,63 @@ namespace GleeBug { + class ScopedCriticalSection + { + PCRITICAL_SECTION cr; + + public: + ScopedCriticalSection(PCRITICAL_SECTION cr) + : cr(cr) + { + EnterCriticalSection(cr); + } + + ~ScopedCriticalSection() + { + LeaveCriticalSection(cr); + } + }; + + template + class LockedPtr + { + PCRITICAL_SECTION locker; + T* ptr; + + public: + explicit LockedPtr(PCRITICAL_SECTION locker, T* ptr) + : locker(locker), ptr(ptr) + { + EnterCriticalSection(locker); + } + + ~LockedPtr() + { + LeaveCriticalSection(locker); + } + + LockedPtr(const LockedPtr &) = delete; + + LockedPtr &operator=(const LockedPtr &) = delete; + + LockedPtr(LockedPtr && other) + : locker(other.locker), ptr(other.ptr) + { + other.locker = nullptr; + other.ptr = nullptr; + } + + /*operator T*() const + { + return ptr; + }*/ + + T* operator->() const + { + return ptr; + } + }; + /** \brief Thread register context. */ @@ -162,7 +219,7 @@ namespace GleeBug \brief Gets a pointer to the context object. \return This function will never return a nullptr. */ - CONTEXT* GetContext(); + LockedPtr GetContext(); /** \brief Sets the CONTEXT. @@ -172,6 +229,7 @@ namespace GleeBug private: CONTEXT mContext; + CRITICAL_SECTION mCr; LPCONTEXT mLazyOldContext = nullptr; HANDLE mLazyThread = nullptr; diff --git a/GleeBug/Debugger.h b/GleeBug/Debugger.h index 8b44897..3fbb6fd 100644 --- a/GleeBug/Debugger.h +++ b/GleeBug/Debugger.h @@ -284,7 +284,7 @@ namespace GleeBug bool mBreakDebugger = false; DEBUG_EVENT mDebugEvent; ProcessMap mProcesses; - bool mIsRunning = false; + bool mIsRunning = false; //TODO: needs a dedicated critical section to prevent ContinueDebugEvent and change of registers to race bool mIsDebugging = false; bool mDetach = false; bool mDetachAndBreak = false; diff --git a/TitanEngineEmulator/Emulator.h b/TitanEngineEmulator/Emulator.h index d34d76b..f3c3a62 100644 --- a/TitanEngineEmulator/Emulator.h +++ b/TitanEngineEmulator/Emulator.h @@ -533,6 +533,7 @@ public: if (!thread || !titcontext) return false; ThreadSuspender suspender(thread, mIsRunning, false); + auto context = thread->registers.GetContext(); memset(titcontext, 0, sizeof(TITAN_ENGINE_CONTEXT_t)); //General purpose registers titcontext->cax = thread->registers.Gax(); @@ -571,7 +572,6 @@ public: titcontext->cs = thread->registers.Cs(); titcontext->ss = thread->registers.Ss(); // x87 - auto context = thread->registers.GetContext(); #ifdef _WIN64 titcontext->x87fpu.ControlWord = context->FltSave.ControlWord; titcontext->x87fpu.StatusWord = context->FltSave.StatusWord; @@ -618,6 +618,7 @@ public: if (!thread || !titcontext) return false; ThreadSuspender suspender(thread, mIsRunning, true); + auto context = thread->registers.GetContext(); // General purpose registers thread->registers.Gax = titcontext->cax; thread->registers.Gcx = titcontext->ccx; @@ -655,7 +656,6 @@ public: thread->registers.Cs = titcontext->cs; thread->registers.Ss = titcontext->ss; // x87 - auto context = thread->registers.GetContext(); #ifdef _WIN64 context->FltSave.ControlWord = titcontext->x87fpu.ControlWord; context->FltSave.StatusWord = titcontext->x87fpu.StatusWord;