//
//---------------------------------------------------------------------------------------
+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),
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);
}
// 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();
// 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.
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
+
};
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)