From 47f80010373ec65a65093f1e990c543f860af29c Mon Sep 17 00:00:00 2001 From: Andrew Au Date: Tue, 9 Oct 2018 17:32:33 -0700 Subject: [PATCH] x86 only stackwalk fix Commit migrated from https://github.com/dotnet/coreclr/commit/b70d04f9112548b1718e1768cf0cb35943724946 --- src/coreclr/src/debug/ee/controller.cpp | 30 ++++++++++++++++++++++++++++++ src/coreclr/src/debug/ee/controller.h | 20 +++++++++----------- 2 files changed, 39 insertions(+), 11 deletions(-) diff --git a/src/coreclr/src/debug/ee/controller.cpp b/src/coreclr/src/debug/ee/controller.cpp index 74d9f11..60d634a 100644 --- a/src/coreclr/src/debug/ee/controller.cpp +++ b/src/coreclr/src/debug/ee/controller.cpp @@ -944,6 +944,11 @@ HRESULT DebuggerController::Initialize() // //--------------------------------------------------------------------------------------- +bool DebuggerController::s_fUnwoundWriteBarrier = false; +DWORD DebuggerController::s_eipBeforeUnwoundWriteBarrier = 0; +DWORD DebuggerController::s_ecxBeforeUnwoundWriteBarrier = 0; +DWORD DebuggerController::s_ebpBeforeUnwoundWriteBarrier = 0; + DebuggerController::DebuggerController(Thread * pThread, AppDomain * pAppDomain) : m_pAppDomain(pAppDomain), m_thread(pThread), @@ -2730,6 +2735,20 @@ DPOSS_ACTION DebuggerController::ScanForTriggers(CORDB_ADDRESS_TYPE *address, tpr != TPR_TRIGGER_ONLY_THIS && DebuggerDataBreakpoint::TriggerDataBreakpoint(thread, context)) { + if (1) /* FIXME : IP range check is required */ + { + // TODO: Comment on the JIT helper as well + DWORD* esp = (DWORD*)context->Esp; + DebuggerController::s_eipBeforeUnwoundWriteBarrier = context->Eip; + DebuggerController::s_ebpBeforeUnwoundWriteBarrier = context->Ebp; + DebuggerController::s_ecxBeforeUnwoundWriteBarrier = context->Ecx; + context->Ebp = *esp; esp++; + context->Ecx = *esp; esp++; + context->Eip = *esp; esp++; + context->Esp = (DWORD)esp; + + DebuggerController::s_fUnwoundWriteBarrier = true; + } DebuggerDataBreakpoint *pDataBreakpoint = new (interopsafe) DebuggerDataBreakpoint(thread); pDcq->dcqEnqueue(pDataBreakpoint, FALSE); } @@ -3015,7 +3034,18 @@ DPOSS_ACTION DebuggerController::DispatchPatchOrSingleStep(Thread *thread, CONTE // If we need to to a re-abort (see below), then save the current IP in the thread's context before we block and // possibly let another func eval get setup. reabort = thread->m_StateNC & Thread::TSNC_DebuggerReAbort; + SENDIPCEVENT_END; + + if (DebuggerController::s_fUnwoundWriteBarrier) + { + DWORD* esp = (DWORD*)context->Esp; + context->Eip = DebuggerController::s_eipBeforeUnwoundWriteBarrier; esp--; + context->Ecx = DebuggerController::s_ecxBeforeUnwoundWriteBarrier; esp--; + context->Ebp = DebuggerController::s_ebpBeforeUnwoundWriteBarrier; esp--; + context->Esp = (DWORD)esp; + DebuggerController::s_fUnwoundWriteBarrier = false; + } if (!atSafePlace) g_pDebugger->DecThreadsAtUnsafePlaces(); diff --git a/src/coreclr/src/debug/ee/controller.h b/src/coreclr/src/debug/ee/controller.h index d73a432..8cc242f 100644 --- a/src/coreclr/src/debug/ee/controller.h +++ b/src/coreclr/src/debug/ee/controller.h @@ -1386,7 +1386,7 @@ public: // the bp. So we pass in an extra flag, fInteruptedBySetIp, to let the controller decide how to handle this. // Since SetIP only works within a single function, this can only be an issue if a thread's current stopping // location and the patch it set are in the same function. (So this could happen for step-over, but never - // setp-out). + // step-out). // This flag will almost always be false. // // Once we actually send the event, we're under the debugger lock, and so the world is stable underneath us. @@ -1414,7 +1414,13 @@ private: bool m_deleted; bool m_fEnableMethodEnter; + static bool s_fUnwoundWriteBarrier; + static DWORD s_eipBeforeUnwoundWriteBarrier; + static DWORD s_ecxBeforeUnwoundWriteBarrier; + static DWORD s_ebpBeforeUnwoundWriteBarrier; + #endif // !DACCESS_COMPILE + }; @@ -1798,16 +1804,8 @@ public: CONTEXT *context = g_pEEInterface->GetThreadFilterContext(thread); - // If we got interupted by SetIp, we just don't send the IPC event. Our triggers are still - // active so no harm done. - if (!fInteruptedBySetIp) - { - g_pDebugger->SendDataBreakpoint(thread, context, this); - return true; - } - - // Controller is still alive, will fire if we hit the breakpoint again. - return false; + g_pDebugger->SendDataBreakpoint(thread, context, this); + return true; } static bool TriggerDataBreakpoint(Thread *thread, CONTEXT * pContext) -- 2.7.4