Skip to content

Commit 62075f1

Browse files
VSadovjkotas
andauthored
[NativeAOT] thread suspension on Unix (#71187)
* missing pieces * fixes * pThreadToHijack * NATIVE_CONTEXT * at safe point * enable TestConcurrentIsBackgroundProperty * couple tweaks * fixes after rebasing * temporarily do not handle multireg returns * support single reg return hijack * disable return hijacking for ARM64 * enable safe point suspend * enable multireg * make gcc happy * fixws for win-x64 * Do not wait for Unhijack. * crude check for VirtualUnwind issue in inline suspend and some tweaks * disable hijacking on ARM64/UNIX * preserve xmm1 * IsUnwindable check * detect not-unwindable code, at least the most common cases. * IsUnwindable tweaks * detect epilogs * hijack in epilogues. * PR feedback (refactoring) * Check the trap flag in `HijackCallback` (optimization) * Apply suggestions from code review Co-authored-by: Jan Kotas <jkotas@microsoft.com> * PR feedback (refactor/renames) * handle "int 3" as not unwindable, not hijackable. Co-authored-by: Jan Kotas <jkotas@microsoft.com>
1 parent f93d0d6 commit 62075f1

31 files changed

+1297
-749
lines changed

src/coreclr/nativeaot/Runtime/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,7 @@ else()
175175
unix/cgroup.cpp
176176
unix/HardwareExceptions.cpp
177177
unix/UnixContext.cpp
178+
unix/UnixSignals.cpp
178179
unix/UnwindHelpers.cpp
179180
unix/UnixNativeCodeManager.cpp
180181
../libunwind/src/Unwind-EHABI.cpp

src/coreclr/nativeaot/Runtime/ICodeManager.h

Lines changed: 32 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ enum GCRefKind : unsigned char
2828
GCRK_Scalar = 0x00,
2929
GCRK_Object = 0x01,
3030
GCRK_Byref = 0x02,
31-
#ifdef TARGET_ARM64
31+
#ifdef TARGET_64BIT
3232
// Composite return kinds for value types returned in two registers (encoded with two bits per register)
3333
GCRK_Scalar_Obj = (GCRK_Object << 2) | GCRK_Scalar,
3434
GCRK_Obj_Obj = (GCRK_Object << 2) | GCRK_Object,
@@ -66,6 +66,35 @@ inline GCRefKind TransitionFrameFlagsToReturnKind(uint64_t transFrameFlags)
6666
return returnKind;
6767
}
6868

69+
#elif defined(TARGET_AMD64)
70+
71+
// Verify that we can use bitwise shifts to convert from GCRefKind to PInvokeTransitionFrameFlags and back
72+
C_ASSERT(PTFF_RAX_IS_GCREF == ((uint64_t)GCRK_Object << 16));
73+
C_ASSERT(PTFF_RAX_IS_BYREF == ((uint64_t)GCRK_Byref << 16));
74+
C_ASSERT(PTFF_RDX_IS_GCREF == ((uint64_t)GCRK_Scalar_Obj << 16));
75+
C_ASSERT(PTFF_RDX_IS_BYREF == ((uint64_t)GCRK_Scalar_Byref << 16));
76+
77+
inline uint64_t ReturnKindToTransitionFrameFlags(GCRefKind returnKind)
78+
{
79+
if (returnKind == GCRK_Scalar)
80+
return 0;
81+
82+
return PTFF_SAVE_RAX | PTFF_SAVE_RDX | ((uint64_t)returnKind << 16);
83+
}
84+
85+
inline GCRefKind TransitionFrameFlagsToReturnKind(uint64_t transFrameFlags)
86+
{
87+
GCRefKind returnKind = (GCRefKind)((transFrameFlags & (PTFF_RAX_IS_GCREF | PTFF_RAX_IS_BYREF | PTFF_RDX_IS_GCREF | PTFF_RDX_IS_BYREF)) >> 16);
88+
#if defined(TARGET_UNIX)
89+
ASSERT((returnKind == GCRK_Scalar) || ((transFrameFlags & PTFF_SAVE_RAX) && (transFrameFlags & PTFF_SAVE_RDX)));
90+
#else
91+
ASSERT((returnKind == GCRK_Scalar) || (transFrameFlags & PTFF_SAVE_RAX));
92+
#endif
93+
return returnKind;
94+
}
95+
96+
#endif
97+
6998
// Extract individual GCRefKind components from a composite return kind
7099
inline GCRefKind ExtractReg0ReturnKind(GCRefKind returnKind)
71100
{
@@ -78,7 +107,6 @@ inline GCRefKind ExtractReg1ReturnKind(GCRefKind returnKind)
78107
ASSERT(returnKind <= GCRK_LastValid);
79108
return (GCRefKind)(returnKind >> 2);
80109
}
81-
#endif // TARGET_ARM64
82110

83111
//
84112
// MethodInfo is placeholder type used to allocate space for MethodInfo. Maximum size
@@ -162,6 +190,8 @@ class ICodeManager
162190
virtual uintptr_t GetConservativeUpperBoundForOutgoingArgs(MethodInfo * pMethodInfo,
163191
REGDISPLAY * pRegisterSet) = 0;
164192

193+
virtual bool IsUnwindable(PTR_VOID pvAddress) = 0;
194+
165195
virtual bool GetReturnAddressHijackInfo(MethodInfo * pMethodInfo,
166196
REGDISPLAY * pRegisterSet, // in
167197
PTR_PTR_VOID * ppvRetAddrLocation, // out

src/coreclr/nativeaot/Runtime/PalRedhawk.h

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -596,8 +596,6 @@ REDHAWK_PALIMPORT bool REDHAWK_PALAPI PalGetCompleteThreadContext(HANDLE hThread
596596
REDHAWK_PALIMPORT bool REDHAWK_PALAPI PalSetThreadContext(HANDLE hThread, _Out_ CONTEXT * pCtx);
597597
REDHAWK_PALIMPORT void REDHAWK_PALAPI PalRestoreContext(CONTEXT * pCtx);
598598

599-
REDHAWK_PALIMPORT bool REDHAWK_PALAPI PalGetThreadContext(HANDLE hThread, _Out_ PAL_LIMITED_CONTEXT * pCtx);
600-
601599
REDHAWK_PALIMPORT int32_t REDHAWK_PALAPI PalGetProcessCpuCount();
602600

603601
// Retrieves the entire range of memory dedicated to the calling thread's stack. This does
@@ -683,6 +681,13 @@ REDHAWK_PALIMPORT uint64_t REDHAWK_PALAPI PalGetTickCount64();
683681
REDHAWK_PALIMPORT void REDHAWK_PALAPI PalTerminateCurrentProcess(uint32_t exitCode);
684682
REDHAWK_PALIMPORT HANDLE REDHAWK_PALAPI PalGetModuleHandleFromPointer(_In_ void* pointer);
685683

684+
#ifdef TARGET_UNIX
685+
struct UNIX_CONTEXT;
686+
#define NATIVE_CONTEXT UNIX_CONTEXT
687+
#else
688+
#define NATIVE_CONTEXT CONTEXT
689+
#endif
690+
686691
#ifdef TARGET_UNIX
687692
REDHAWK_PALIMPORT void REDHAWK_PALAPI PalSetHardwareExceptionHandler(PHARDWARE_EXCEPTION_HANDLER handler);
688693
#else
@@ -693,8 +698,9 @@ typedef uint32_t (__stdcall *BackgroundCallback)(_In_opt_ void* pCallbackContext
693698
REDHAWK_PALIMPORT bool REDHAWK_PALAPI PalStartBackgroundGCThread(_In_ BackgroundCallback callback, _In_opt_ void* pCallbackContext);
694699
REDHAWK_PALIMPORT bool REDHAWK_PALAPI PalStartFinalizerThread(_In_ BackgroundCallback callback, _In_opt_ void* pCallbackContext);
695700

696-
typedef UInt32_BOOL (*PalHijackCallback)(HANDLE hThread, _In_ PAL_LIMITED_CONTEXT* pThreadContext, _In_opt_ void* pCallbackContext);
697-
REDHAWK_PALIMPORT uint32_t REDHAWK_PALAPI PalHijack(HANDLE hThread, _In_ PalHijackCallback callback, _In_opt_ void* pCallbackContext);
701+
typedef void (*PalHijackCallback)(_In_ NATIVE_CONTEXT* pThreadContext, _In_opt_ void* pThreadToHijack);
702+
REDHAWK_PALIMPORT void REDHAWK_PALAPI PalHijack(HANDLE hThread, _In_opt_ void* pThreadToHijack);
703+
REDHAWK_PALIMPORT UInt32_BOOL REDHAWK_PALAPI PalRegisterHijackCallback(_In_ PalHijackCallback callback);
698704

699705
#ifdef FEATURE_ETW
700706
REDHAWK_PALIMPORT bool REDHAWK_PALAPI PalEventEnabled(REGHANDLE regHandle, _In_ const EVENT_DESCRIPTOR* eventDescriptor);

src/coreclr/nativeaot/Runtime/StackFrameIterator.cpp

Lines changed: 79 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,10 @@
2727
#include "RuntimeInstance.h"
2828
#include "rhbinder.h"
2929

30+
#ifdef TARGET_UNIX
31+
#include "UnixContext.h"
32+
#endif
33+
3034
// warning C4061: enumerator '{blah}' in switch of enum '{blarg}' is not explicitly handled by a case label
3135
#pragma warning(disable:4061)
3236

@@ -93,13 +97,11 @@ StackFrameIterator::StackFrameIterator(Thread * pThreadToWalk, PInvokeTransition
9397
STRESS_LOG0(LF_STACKWALK, LL_INFO10000, "----Init---- [ GC ]\n");
9498
ASSERT(!pThreadToWalk->DangerousCrossThreadIsHijacked());
9599

96-
#ifdef FEATURE_SUSPEND_REDIRECTION
97-
if (pInitialTransitionFrame == REDIRECTED_THREAD_MARKER)
100+
if (pInitialTransitionFrame == INTERRUPTED_THREAD_MARKER)
98101
{
99-
InternalInit(pThreadToWalk, pThreadToWalk->GetRedirectionContext(), GcStackWalkFlags | ActiveStackFrame);
102+
InternalInit(pThreadToWalk, pThreadToWalk->GetInterruptedContext(), GcStackWalkFlags | ActiveStackFrame);
100103
}
101104
else
102-
#endif
103105
{
104106
InternalInit(pThreadToWalk, pInitialTransitionFrame, GcStackWalkFlags);
105107
}
@@ -109,7 +111,14 @@ StackFrameIterator::StackFrameIterator(Thread * pThreadToWalk, PInvokeTransition
109111

110112
StackFrameIterator::StackFrameIterator(Thread * pThreadToWalk, PTR_PAL_LIMITED_CONTEXT pCtx)
111113
{
112-
STRESS_LOG0(LF_STACKWALK, LL_INFO10000, "----Init---- [ hijack ]\n");
114+
STRESS_LOG0(LF_STACKWALK, LL_INFO10000, "----Init with limited ctx---- [ hijack ]\n");
115+
InternalInit(pThreadToWalk, pCtx, 0);
116+
PrepareToYieldFrame();
117+
}
118+
119+
StackFrameIterator::StackFrameIterator(Thread* pThreadToWalk, NATIVE_CONTEXT* pCtx)
120+
{
121+
STRESS_LOG0(LF_STACKWALK, LL_INFO10000, "----Init with native ctx---- [ hijack ]\n");
113122
InternalInit(pThreadToWalk, pCtx, 0);
114123
PrepareToYieldFrame();
115124
}
@@ -283,15 +292,11 @@ void StackFrameIterator::InternalInit(Thread * pThreadToWalk, PInvokeTransitionF
283292
if (pFrame->m_Flags & PTFF_SAVE_R11) { m_RegDisplay.pR11 = pPreservedRegsCursor++; }
284293
#endif // TARGET_AMD64
285294

286-
if (pFrame->m_Flags & PTFF_RAX_IS_GCREF)
287-
{
288-
m_pHijackedReturnValue = (PTR_RtuObjectRef) m_RegDisplay.pRax;
289-
m_HijackedReturnValueKind = GCRK_Object;
290-
}
291-
if (pFrame->m_Flags & PTFF_RAX_IS_BYREF)
295+
GCRefKind retValueKind = TransitionFrameFlagsToReturnKind(pFrame->m_Flags);
296+
if (retValueKind != GCRK_Scalar)
292297
{
293-
m_pHijackedReturnValue = (PTR_RtuObjectRef) m_RegDisplay.pRax;
294-
m_HijackedReturnValueKind = GCRK_Byref;
298+
m_pHijackedReturnValue = (PTR_RtuObjectRef)m_RegDisplay.pRax;
299+
m_HijackedReturnValueKind = retValueKind;
295300
}
296301

297302
#endif // TARGET_ARM
@@ -508,10 +513,9 @@ void StackFrameIterator::InternalInit(Thread * pThreadToWalk, PTR_PAL_LIMITED_CO
508513
#endif // TARGET_ARM
509514
}
510515

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)
516+
// Prepare to start a stack walk from the context listed in the supplied NATIVE_CONTEXT.
517+
// The supplied context can describe a location in managed code.
518+
void StackFrameIterator::InternalInit(Thread * pThreadToWalk, NATIVE_CONTEXT* pCtx, uint32_t dwFlags)
515519
{
516520
ASSERT((dwFlags & MethodStateCalculated) == 0);
517521

@@ -524,10 +528,8 @@ void StackFrameIterator::InternalInit(Thread * pThreadToWalk, CONTEXT* pCtx, uin
524528
// properly walk it in parallel.
525529
ResetNextExInfoForSP(pCtx->GetSp());
526530

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+
// This codepath is used by the hijack stackwalk. The IP must be in managed code.
532+
ASSERT(m_pInstance->IsManaged(dac_cast<PTR_VOID>(pCtx->GetIp())));
531533

532534
//
533535
// control state
@@ -536,82 +538,90 @@ void StackFrameIterator::InternalInit(Thread * pThreadToWalk, CONTEXT* pCtx, uin
536538
m_RegDisplay.SP = pCtx->GetSp();
537539
m_RegDisplay.IP = pCtx->GetIp();
538540

541+
#ifdef TARGET_UNIX
542+
#define PTR_TO_REG(ptr, reg) (&((ptr)->reg()))
543+
#else
544+
#define PTR_TO_REG(ptr, reg) (&((ptr)->reg))
545+
#endif
546+
539547
#ifdef TARGET_ARM64
540548

541-
m_RegDisplay.pIP = PTR_TO_MEMBER(CONTEXT, pCtx, Pc);
549+
m_RegDisplay.pIP = (PTR_PCODE)PTR_TO_REG(pCtx, Pc);
542550

543551
//
544552
// preserved regs
545553
//
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);
554+
m_RegDisplay.pX19 = (PTR_UIntNative)PTR_TO_REG(pCtx, X19);
555+
m_RegDisplay.pX20 = (PTR_UIntNative)PTR_TO_REG(pCtx, X20);
556+
m_RegDisplay.pX21 = (PTR_UIntNative)PTR_TO_REG(pCtx, X21);
557+
m_RegDisplay.pX22 = (PTR_UIntNative)PTR_TO_REG(pCtx, X22);
558+
m_RegDisplay.pX23 = (PTR_UIntNative)PTR_TO_REG(pCtx, X23);
559+
m_RegDisplay.pX24 = (PTR_UIntNative)PTR_TO_REG(pCtx, X24);
560+
m_RegDisplay.pX25 = (PTR_UIntNative)PTR_TO_REG(pCtx, X25);
561+
m_RegDisplay.pX26 = (PTR_UIntNative)PTR_TO_REG(pCtx, X26);
562+
m_RegDisplay.pX27 = (PTR_UIntNative)PTR_TO_REG(pCtx, X27);
563+
m_RegDisplay.pX28 = (PTR_UIntNative)PTR_TO_REG(pCtx, X28);
564+
m_RegDisplay.pFP = (PTR_UIntNative)PTR_TO_REG(pCtx, Fp);
565+
m_RegDisplay.pLR = (PTR_UIntNative)PTR_TO_REG(pCtx, Lr);
558566

559567
//
560568
// scratch regs
561569
//
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);
570+
m_RegDisplay.pX0 = (PTR_UIntNative)PTR_TO_REG(pCtx, X0);
571+
m_RegDisplay.pX1 = (PTR_UIntNative)PTR_TO_REG(pCtx, X1);
572+
m_RegDisplay.pX2 = (PTR_UIntNative)PTR_TO_REG(pCtx, X2);
573+
m_RegDisplay.pX3 = (PTR_UIntNative)PTR_TO_REG(pCtx, X3);
574+
m_RegDisplay.pX4 = (PTR_UIntNative)PTR_TO_REG(pCtx, X4);
575+
m_RegDisplay.pX5 = (PTR_UIntNative)PTR_TO_REG(pCtx, X5);
576+
m_RegDisplay.pX6 = (PTR_UIntNative)PTR_TO_REG(pCtx, X6);
577+
m_RegDisplay.pX7 = (PTR_UIntNative)PTR_TO_REG(pCtx, X7);
578+
m_RegDisplay.pX8 = (PTR_UIntNative)PTR_TO_REG(pCtx, X8);
579+
m_RegDisplay.pX9 = (PTR_UIntNative)PTR_TO_REG(pCtx, X9);
580+
m_RegDisplay.pX10 = (PTR_UIntNative)PTR_TO_REG(pCtx, X10);
581+
m_RegDisplay.pX11 = (PTR_UIntNative)PTR_TO_REG(pCtx, X11);
582+
m_RegDisplay.pX12 = (PTR_UIntNative)PTR_TO_REG(pCtx, X12);
583+
m_RegDisplay.pX13 = (PTR_UIntNative)PTR_TO_REG(pCtx, X13);
584+
m_RegDisplay.pX14 = (PTR_UIntNative)PTR_TO_REG(pCtx, X14);
585+
m_RegDisplay.pX15 = (PTR_UIntNative)PTR_TO_REG(pCtx, X15);
586+
m_RegDisplay.pX16 = (PTR_UIntNative)PTR_TO_REG(pCtx, X16);
587+
m_RegDisplay.pX17 = (PTR_UIntNative)PTR_TO_REG(pCtx, X17);
588+
m_RegDisplay.pX18 = (PTR_UIntNative)PTR_TO_REG(pCtx, X18);
581589

582590
#elif defined(TARGET_X86) || defined(TARGET_AMD64)
583591

584-
m_RegDisplay.pIP = (PTR_PCODE)PTR_TO_MEMBER(CONTEXT, pCtx, Rip);
592+
m_RegDisplay.pIP = (PTR_PCODE)PTR_TO_REG(pCtx, Rip);
585593

586594
//
587595
// preserved regs
588596
//
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);
597+
m_RegDisplay.pRbp = (PTR_UIntNative)PTR_TO_REG(pCtx, Rbp);
598+
m_RegDisplay.pRsi = (PTR_UIntNative)PTR_TO_REG(pCtx, Rsi);
599+
m_RegDisplay.pRdi = (PTR_UIntNative)PTR_TO_REG(pCtx, Rdi);
600+
m_RegDisplay.pRbx = (PTR_UIntNative)PTR_TO_REG(pCtx, Rbx);
593601
#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);
602+
m_RegDisplay.pR12 = (PTR_UIntNative)PTR_TO_REG(pCtx, R12);
603+
m_RegDisplay.pR13 = (PTR_UIntNative)PTR_TO_REG(pCtx, R13);
604+
m_RegDisplay.pR14 = (PTR_UIntNative)PTR_TO_REG(pCtx, R14);
605+
m_RegDisplay.pR15 = (PTR_UIntNative)PTR_TO_REG(pCtx, R15);
598606
#endif // TARGET_AMD64
599607

600608
//
601609
// scratch regs
602610
//
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);
611+
m_RegDisplay.pRax = (PTR_UIntNative)PTR_TO_REG(pCtx, Rax);
612+
m_RegDisplay.pRcx = (PTR_UIntNative)PTR_TO_REG(pCtx, Rcx);
613+
m_RegDisplay.pRdx = (PTR_UIntNative)PTR_TO_REG(pCtx, Rdx);
606614
#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);
615+
m_RegDisplay.pR8 = (PTR_UIntNative)PTR_TO_REG(pCtx, R8);
616+
m_RegDisplay.pR9 = (PTR_UIntNative)PTR_TO_REG(pCtx, R9);
617+
m_RegDisplay.pR10 = (PTR_UIntNative)PTR_TO_REG(pCtx, R10);
618+
m_RegDisplay.pR11 = (PTR_UIntNative)PTR_TO_REG(pCtx, R11);
611619
#endif // TARGET_AMD64
612620
#else
613621
PORTABILITY_ASSERT("StackFrameIterator::InternalInit");
614622
#endif // TARGET_ARM
623+
624+
#undef PTR_TO_REG
615625
}
616626

617627
PTR_VOID StackFrameIterator::HandleExCollide(PTR_ExInfo pExInfo)

src/coreclr/nativeaot/Runtime/StackFrameIterator.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ class StackFrameIterator
3434
public:
3535
StackFrameIterator() {}
3636
StackFrameIterator(Thread * pThreadToWalk, PInvokeTransitionFrame* pInitialTransitionFrame);
37+
StackFrameIterator(Thread* pThreadToWalk, NATIVE_CONTEXT* pCtx);
3738
StackFrameIterator(Thread * pThreadToWalk, PTR_PAL_LIMITED_CONTEXT pCtx);
3839

3940
bool IsValid();
@@ -82,7 +83,7 @@ class StackFrameIterator
8283

8384
void InternalInit(Thread * pThreadToWalk, PTR_PInvokeTransitionFrame pFrame, uint32_t dwFlags); // GC stackwalk
8485
void InternalInit(Thread * pThreadToWalk, PTR_PAL_LIMITED_CONTEXT pCtx, uint32_t dwFlags); // EH and hijack stackwalk, and collided unwind
85-
void InternalInit(Thread * pThreadToWalk, CONTEXT* pCtx, uint32_t dwFlags); // GC stackwalk of redirected thread
86+
void InternalInit(Thread * pThreadToWalk, NATIVE_CONTEXT* pCtx, uint32_t dwFlags); // GC stackwalk of redirected thread
8687

8788
void InternalInitForEH(Thread * pThreadToWalk, PAL_LIMITED_CONTEXT * pCtx, bool instructionFault); // EH stackwalk
8889
void InternalInitForStackTrace(); // Environment.StackTrace

src/coreclr/nativeaot/Runtime/amd64/AsmMacros.inc

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -365,11 +365,11 @@ PTFF_SAVE_R14 equ 00000040h
365365
PTFF_SAVE_R15 equ 00000080h
366366
PTFF_SAVE_ALL_PRESERVED equ 000000F7h ;; NOTE: RBP is not included in this set!
367367
PTFF_SAVE_RSP equ 00008000h
368-
PTFF_SAVE_RAX equ 00000100h ;; RAX is saved if it contains a GC ref and we're in hijack handler
368+
PTFF_SAVE_RAX equ 00000100h ;; RAX is saved in hijack handler - in case it contains a GC ref
369369
PTFF_SAVE_ALL_SCRATCH equ 00007F00h
370370
PTFF_RAX_IS_GCREF equ 00010000h ;; iff PTFF_SAVE_RAX: set -> eax is Object, clear -> eax is scalar
371371
PTFF_RAX_IS_BYREF equ 00020000h ;; iff PTFF_SAVE_RAX: set -> eax is ByRef, clear -> eax is Object or scalar
372-
PTFF_THREAD_ABORT equ 00040000h ;; indicates that ThreadAbortException should be thrown when returning from the transition
372+
PTFF_THREAD_ABORT equ 00100000h ;; indicates that ThreadAbortException should be thrown when returning from the transition
373373

374374
;; These must match the TrapThreadsFlags enum
375375
TrapThreadsFlags_None equ 0

0 commit comments

Comments
 (0)