@@ -92,7 +92,18 @@ StackFrameIterator::StackFrameIterator(Thread * pThreadToWalk, PInvokeTransition
9292{
9393 STRESS_LOG0 (LF_STACKWALK, LL_INFO10000, " ----Init---- [ GC ]\n " );
9494 ASSERT (!pThreadToWalk->DangerousCrossThreadIsHijacked ());
95- InternalInit (pThreadToWalk, pInitialTransitionFrame, GcStackWalkFlags);
95+
96+ #ifdef FEATURE_SUSPEND_REDIRECTION
97+ if (pInitialTransitionFrame == REDIRECTED_THREAD_MARKER)
98+ {
99+ InternalInit (pThreadToWalk, pThreadToWalk->GetRedirectionContext (), GcStackWalkFlags | ActiveStackFrame);
100+ }
101+ else
102+ #endif
103+ {
104+ InternalInit (pThreadToWalk, pInitialTransitionFrame, GcStackWalkFlags);
105+ }
106+
96107 PrepareToYieldFrame ();
97108}
98109
@@ -497,6 +508,112 @@ void StackFrameIterator::InternalInit(Thread * pThreadToWalk, PTR_PAL_LIMITED_CO
497508#endif // TARGET_ARM
498509}
499510
511+ // Prepare to start a stack walk from the context listed in the supplied CONTEXT.
512+ // The supplied context can describe a location in either managed or unmanaged code. In the
513+ // latter case the iterator is left in an invalid state when this function returns.
514+ void StackFrameIterator::InternalInit (Thread * pThreadToWalk, CONTEXT* pCtx, uint32_t dwFlags)
515+ {
516+ ASSERT ((dwFlags & MethodStateCalculated) == 0 );
517+
518+ EnterInitialInvalidState (pThreadToWalk);
519+
520+ m_dwFlags = dwFlags;
521+
522+ // We need to walk the ExInfo chain in parallel with the stackwalk so that we know when we cross over
523+ // exception throw points. So we must find our initial point in the ExInfo chain here so that we can
524+ // properly walk it in parallel.
525+ ResetNextExInfoForSP (pCtx->GetSp ());
526+
527+ // This codepath is used by the hijack stackwalk and we can get arbitrary ControlPCs from there. If this
528+ // context has a non-managed control PC, then we're done.
529+ if (!m_pInstance->IsManaged (dac_cast<PTR_VOID>(pCtx->GetIp ())))
530+ return ;
531+
532+ //
533+ // control state
534+ //
535+ SetControlPC (dac_cast<PTR_VOID>(pCtx->GetIp ()));
536+ m_RegDisplay.SP = pCtx->GetSp ();
537+ m_RegDisplay.IP = pCtx->GetIp ();
538+
539+ #ifdef TARGET_ARM64
540+
541+ m_RegDisplay.pIP = PTR_TO_MEMBER (CONTEXT, pCtx, Pc);
542+
543+ //
544+ // preserved regs
545+ //
546+ m_RegDisplay.pX19 = PTR_TO_MEMBER (CONTEXT, pCtx, X19);
547+ m_RegDisplay.pX20 = PTR_TO_MEMBER (CONTEXT, pCtx, X20);
548+ m_RegDisplay.pX21 = PTR_TO_MEMBER (CONTEXT, pCtx, X21);
549+ m_RegDisplay.pX22 = PTR_TO_MEMBER (CONTEXT, pCtx, X22);
550+ m_RegDisplay.pX23 = PTR_TO_MEMBER (CONTEXT, pCtx, X23);
551+ m_RegDisplay.pX24 = PTR_TO_MEMBER (CONTEXT, pCtx, X24);
552+ m_RegDisplay.pX25 = PTR_TO_MEMBER (CONTEXT, pCtx, X25);
553+ m_RegDisplay.pX26 = PTR_TO_MEMBER (CONTEXT, pCtx, X26);
554+ m_RegDisplay.pX27 = PTR_TO_MEMBER (CONTEXT, pCtx, X27);
555+ m_RegDisplay.pX28 = PTR_TO_MEMBER (CONTEXT, pCtx, X28);
556+ m_RegDisplay.pFP = PTR_TO_MEMBER (CONTEXT, pCtx, Fp);
557+ m_RegDisplay.pLR = PTR_TO_MEMBER (CONTEXT, pCtx, Lr);
558+
559+ //
560+ // scratch regs
561+ //
562+ m_RegDisplay.pX0 = PTR_TO_MEMBER (CONTEXT, pCtx, X0);
563+ m_RegDisplay.pX1 = PTR_TO_MEMBER (CONTEXT, pCtx, X1);
564+ m_RegDisplay.pX2 = PTR_TO_MEMBER (CONTEXT, pCtx, X2);
565+ m_RegDisplay.pX3 = PTR_TO_MEMBER (CONTEXT, pCtx, X3);
566+ m_RegDisplay.pX4 = PTR_TO_MEMBER (CONTEXT, pCtx, X4);
567+ m_RegDisplay.pX5 = PTR_TO_MEMBER (CONTEXT, pCtx, X5);
568+ m_RegDisplay.pX6 = PTR_TO_MEMBER (CONTEXT, pCtx, X6);
569+ m_RegDisplay.pX7 = PTR_TO_MEMBER (CONTEXT, pCtx, X7);
570+ m_RegDisplay.pX8 = PTR_TO_MEMBER (CONTEXT, pCtx, X8);
571+ m_RegDisplay.pX9 = PTR_TO_MEMBER (CONTEXT, pCtx, X9);
572+ m_RegDisplay.pX10 = PTR_TO_MEMBER (CONTEXT, pCtx, X10);
573+ m_RegDisplay.pX11 = PTR_TO_MEMBER (CONTEXT, pCtx, X11);
574+ m_RegDisplay.pX12 = PTR_TO_MEMBER (CONTEXT, pCtx, X12);
575+ m_RegDisplay.pX13 = PTR_TO_MEMBER (CONTEXT, pCtx, X13);
576+ m_RegDisplay.pX14 = PTR_TO_MEMBER (CONTEXT, pCtx, X14);
577+ m_RegDisplay.pX15 = PTR_TO_MEMBER (CONTEXT, pCtx, X15);
578+ m_RegDisplay.pX16 = PTR_TO_MEMBER (CONTEXT, pCtx, X16);
579+ m_RegDisplay.pX17 = PTR_TO_MEMBER (CONTEXT, pCtx, X17);
580+ m_RegDisplay.pX18 = PTR_TO_MEMBER (CONTEXT, pCtx, X18);
581+
582+ #elif defined(TARGET_X86) || defined(TARGET_AMD64)
583+
584+ m_RegDisplay.pIP = (PTR_PCODE)PTR_TO_MEMBER (CONTEXT, pCtx, Rip);
585+
586+ //
587+ // preserved regs
588+ //
589+ m_RegDisplay.pRbp = (PTR_UIntNative)PTR_TO_MEMBER (CONTEXT, pCtx, Rbp);
590+ m_RegDisplay.pRsi = (PTR_UIntNative)PTR_TO_MEMBER (CONTEXT, pCtx, Rsi);
591+ m_RegDisplay.pRdi = (PTR_UIntNative)PTR_TO_MEMBER (CONTEXT, pCtx, Rdi);
592+ m_RegDisplay.pRbx = (PTR_UIntNative)PTR_TO_MEMBER (CONTEXT, pCtx, Rbx);
593+ #ifdef TARGET_AMD64
594+ m_RegDisplay.pR12 = (PTR_UIntNative)PTR_TO_MEMBER (CONTEXT, pCtx, R12);
595+ m_RegDisplay.pR13 = (PTR_UIntNative)PTR_TO_MEMBER (CONTEXT, pCtx, R13);
596+ m_RegDisplay.pR14 = (PTR_UIntNative)PTR_TO_MEMBER (CONTEXT, pCtx, R14);
597+ m_RegDisplay.pR15 = (PTR_UIntNative)PTR_TO_MEMBER (CONTEXT, pCtx, R15);
598+ #endif // TARGET_AMD64
599+
600+ //
601+ // scratch regs
602+ //
603+ m_RegDisplay.pRax = (PTR_UIntNative)PTR_TO_MEMBER (CONTEXT, pCtx, Rax);
604+ m_RegDisplay.pRcx = (PTR_UIntNative)PTR_TO_MEMBER (CONTEXT, pCtx, Rcx);
605+ m_RegDisplay.pRdx = (PTR_UIntNative)PTR_TO_MEMBER (CONTEXT, pCtx, Rdx);
606+ #ifdef TARGET_AMD64
607+ m_RegDisplay.pR8 = (PTR_UIntNative)PTR_TO_MEMBER (CONTEXT, pCtx, R8);
608+ m_RegDisplay.pR9 = (PTR_UIntNative)PTR_TO_MEMBER (CONTEXT, pCtx, R9);
609+ m_RegDisplay.pR10 = (PTR_UIntNative)PTR_TO_MEMBER (CONTEXT, pCtx, R10);
610+ m_RegDisplay.pR11 = (PTR_UIntNative)PTR_TO_MEMBER (CONTEXT, pCtx, R11);
611+ #endif // TARGET_AMD64
612+ #else
613+ PORTABILITY_ASSERT (" StackFrameIterator::InternalInit" );
614+ #endif // TARGET_ARM
615+ }
616+
500617PTR_VOID StackFrameIterator::HandleExCollide (PTR_ExInfo pExInfo)
501618{
502619 STRESS_LOG3 (LF_STACKWALK, LL_INFO10000, " [ ex collide ] kind = %d, pass = %d, idxCurClause = %d\n " ,
@@ -1290,7 +1407,7 @@ void StackFrameIterator::NextInternal()
12901407{
12911408UnwindOutOfCurrentManagedFrame:
12921409 ASSERT (m_dwFlags & MethodStateCalculated);
1293- m_dwFlags &= ~(ExCollide|MethodStateCalculated|UnwoundReversePInvoke);
1410+ m_dwFlags &= ~(ExCollide|MethodStateCalculated|UnwoundReversePInvoke|ActiveStackFrame );
12941411 ASSERT (IsValid ());
12951412
12961413 m_pHijackedReturnValue = NULL ;
@@ -1640,6 +1757,12 @@ MethodInfo * StackFrameIterator::GetMethodInfo()
16401757 return &m_methodInfo;
16411758}
16421759
1760+ bool StackFrameIterator::IsActiveStackFrame ()
1761+ {
1762+ ASSERT (IsValid ());
1763+ return (m_dwFlags & ActiveStackFrame) != 0 ;
1764+ }
1765+
16431766#ifdef DACCESS_COMPILE
16441767#define FAILFAST_OR_DAC_RETURN_FALSE (x ) if (!(x)) return false ;
16451768#else
0 commit comments