diff --git a/src/coreclr/gcdump/gcdumpnonx86.cpp b/src/coreclr/gcdump/gcdumpnonx86.cpp index 919bf60d886703..d4366069f14a7f 100644 --- a/src/coreclr/gcdump/gcdumpnonx86.cpp +++ b/src/coreclr/gcdump/gcdumpnonx86.cpp @@ -361,7 +361,6 @@ size_t GCDump::DumpGCTable(PTR_CBYTE gcInfoBlock, | DECODE_GENERICS_INST_CONTEXT | DECODE_GC_LIFETIMES | DECODE_PROLOG_LENGTH - | DECODE_RETURN_KIND #if defined(TARGET_ARM) || defined(TARGET_ARM64) || defined(TARGET_RISCV64) || defined(TARGET_LOONGARCH64) | DECODE_HAS_TAILCALLS #endif @@ -502,9 +501,6 @@ size_t GCDump::DumpGCTable(PTR_CBYTE gcInfoBlock, gcPrintf("Size of parameter area: %x\n", hdrdecoder.GetSizeOfStackParameterArea()); #endif - ReturnKind returnKind = hdrdecoder.GetReturnKind(); - gcPrintf("Return Kind: %s\n", ReturnKindToString(returnKind)); - UINT32 cbEncodedMethodSize = hdrdecoder.GetCodeLength(); gcPrintf("Code size: %x\n", cbEncodedMethodSize); diff --git a/src/coreclr/inc/eetwain.h b/src/coreclr/inc/eetwain.h index 271e0de8ecb7f4..32801bd23c540c 100644 --- a/src/coreclr/inc/eetwain.h +++ b/src/coreclr/inc/eetwain.h @@ -306,7 +306,7 @@ virtual size_t GetFunctionSize(GCInfoToken gcInfoToken) = 0; * returns true. * If hijacking is not possible for some reason, it return false. */ -virtual bool GetReturnAddressHijackInfo(GCInfoToken gcInfoToken, ReturnKind * returnKind) = 0; +virtual bool GetReturnAddressHijackInfo(GCInfoToken gcInfoToken X86_ARG(ReturnKind * returnKind)) = 0; #ifndef USE_GC_INFO_DECODER /* @@ -575,7 +575,7 @@ size_t GetFunctionSize(GCInfoToken gcInfoToken); * returns true. * If hijacking is not possible for some reason, it return false. */ -virtual bool GetReturnAddressHijackInfo(GCInfoToken gcInfoToken, ReturnKind * returnKind); +virtual bool GetReturnAddressHijackInfo(GCInfoToken gcInfoToken X86_ARG(ReturnKind * returnKind)); #ifndef USE_GC_INFO_DECODER /* diff --git a/src/coreclr/inc/gcinfodecoder.h b/src/coreclr/inc/gcinfodecoder.h index d91e10bc081d21..0b51833ee19d5e 100644 --- a/src/coreclr/inc/gcinfodecoder.h +++ b/src/coreclr/inc/gcinfodecoder.h @@ -222,7 +222,6 @@ enum GcInfoDecoderFlags DECODE_PROLOG_LENGTH = 0x400, // length of the prolog (used to avoid reporting generics context) DECODE_EDIT_AND_CONTINUE = 0x800, DECODE_REVERSE_PINVOKE_VAR = 0x1000, - DECODE_RETURN_KIND = 0x2000, #if defined(TARGET_ARM) || defined(TARGET_ARM64) || defined(TARGET_LOONGARCH64) || defined(TARGET_RISCV64) DECODE_HAS_TAILCALLS = 0x4000, #endif // TARGET_ARM || TARGET_ARM64 || TARGET_LOONGARCH64 @@ -582,7 +581,6 @@ class GcInfoDecoder #if defined(TARGET_ARM) || defined(TARGET_ARM64) || defined(TARGET_LOONGARCH64) || defined(TARGET_RISCV64) bool HasTailCalls(); #endif // TARGET_ARM || TARGET_ARM64 || TARGET_LOONGARCH64 || defined(TARGET_RISCV64) - ReturnKind GetReturnKind(); UINT32 GetCodeLength(); UINT32 GetStackBaseRegister(); UINT32 GetSizeOfEditAndContinuePreservedArea(); @@ -615,7 +613,6 @@ class GcInfoDecoder #ifdef TARGET_ARM64 UINT32 m_SizeOfEditAndContinueFixedStackFrame; #endif - ReturnKind m_ReturnKind; #ifdef PARTIALLY_INTERRUPTIBLE_GC_SUPPORTED UINT32 m_NumSafePoints; UINT32 m_SafePointIndex; diff --git a/src/coreclr/nativeaot/Runtime/AsmOffsets.h b/src/coreclr/nativeaot/Runtime/AsmOffsets.h index cb6bf8842e04b9..ef5031560bdc43 100644 --- a/src/coreclr/nativeaot/Runtime/AsmOffsets.h +++ b/src/coreclr/nativeaot/Runtime/AsmOffsets.h @@ -52,9 +52,11 @@ ASM_OFFSET( 30, 48, Thread, m_pTransitionFrame) ASM_OFFSET( 34, 50, Thread, m_pDeferredTransitionFrame) ASM_OFFSET( 44, 70, Thread, m_ppvHijackedReturnAddressLocation) ASM_OFFSET( 48, 78, Thread, m_pvHijackedReturnAddress) -ASM_OFFSET( 4c, 80, Thread, m_uHijackedReturnValueFlags) -ASM_OFFSET( 50, 88, Thread, m_pExInfoStackHead) -ASM_OFFSET( 54, 90, Thread, m_threadAbortException) +ASM_OFFSET( 4c, 80, Thread, m_pExInfoStackHead) +ASM_OFFSET( 50, 88, Thread, m_threadAbortException) +#ifdef TARGET_X86 +ASM_OFFSET( 54, FF, Thread, m_uHijackedReturnValueFlags) +#endif ASM_SIZEOF( 14, 20, EHEnum) diff --git a/src/coreclr/nativeaot/Runtime/ICodeManager.h b/src/coreclr/nativeaot/Runtime/ICodeManager.h index f88304a40e8682..0fd8f60a5458fd 100644 --- a/src/coreclr/nativeaot/Runtime/ICodeManager.h +++ b/src/coreclr/nativeaot/Runtime/ICodeManager.h @@ -28,92 +28,11 @@ enum GCRefKind : unsigned char GCRK_Scalar = 0x00, GCRK_Object = 0x01, GCRK_Byref = 0x02, -#ifdef TARGET_64BIT - // Composite return kinds for value types returned in two registers (encoded with two bits per register) - GCRK_Scalar_Obj = (GCRK_Object << 2) | GCRK_Scalar, - GCRK_Obj_Obj = (GCRK_Object << 2) | GCRK_Object, - GCRK_Byref_Obj = (GCRK_Object << 2) | GCRK_Byref, - GCRK_Scalar_Byref = (GCRK_Byref << 2) | GCRK_Scalar, - GCRK_Obj_Byref = (GCRK_Byref << 2) | GCRK_Object, - GCRK_Byref_Byref = (GCRK_Byref << 2) | GCRK_Byref, - - GCRK_LastValid = GCRK_Byref_Byref, -#else // TARGET_ARM64 GCRK_LastValid = GCRK_Byref, -#endif // TARGET_ARM64 GCRK_Unknown = 0xFF, }; -#ifdef TARGET_ARM64 -// Verify that we can use bitwise shifts to convert from GCRefKind to PInvokeTransitionFrameFlags and back -C_ASSERT(PTFF_X0_IS_GCREF == ((uint64_t)GCRK_Object << 32)); -C_ASSERT(PTFF_X0_IS_BYREF == ((uint64_t)GCRK_Byref << 32)); -C_ASSERT(PTFF_X1_IS_GCREF == ((uint64_t)GCRK_Scalar_Obj << 32)); -C_ASSERT(PTFF_X1_IS_BYREF == ((uint64_t)GCRK_Scalar_Byref << 32)); - -inline uint64_t ReturnKindToTransitionFrameFlags(GCRefKind returnKind) -{ - // just need to report gc ref bits here. - // appropriate PTFF_SAVE_ bits will be added by the frame building routine. - return ((uint64_t)returnKind << 32); -} - -inline GCRefKind TransitionFrameFlagsToReturnKind(uint64_t transFrameFlags) -{ - GCRefKind returnKind = (GCRefKind)((transFrameFlags & (PTFF_X0_IS_GCREF | PTFF_X0_IS_BYREF | PTFF_X1_IS_GCREF | PTFF_X1_IS_BYREF)) >> 32); - ASSERT((returnKind == GCRK_Scalar) || ((transFrameFlags & PTFF_SAVE_X0) && (transFrameFlags & PTFF_SAVE_X1))); - return returnKind; -} - -#elif defined(TARGET_LOONGARCH64) -// Verify that we can use bitwise shifts to convert from GCRefKind to PInvokeTransitionFrameFlags and back -C_ASSERT(PTFF_R4_IS_GCREF == ((uint64_t)GCRK_Object << 31)); -C_ASSERT(PTFF_R4_IS_BYREF == ((uint64_t)GCRK_Byref << 31)); -C_ASSERT(PTFF_R5_IS_GCREF == ((uint64_t)GCRK_Scalar_Obj << 31)); -C_ASSERT(PTFF_R5_IS_BYREF == ((uint64_t)GCRK_Scalar_Byref << 31)); - -inline uint64_t ReturnKindToTransitionFrameFlags(GCRefKind returnKind) -{ - // just need to report gc ref bits here. - // appropriate PTFF_SAVE_ bits will be added by the frame building routine. - return ((uint64_t)returnKind << 31); -} - -inline GCRefKind TransitionFrameFlagsToReturnKind(uint64_t transFrameFlags) -{ - GCRefKind returnKind = (GCRefKind)((transFrameFlags & (PTFF_R4_IS_GCREF | PTFF_R4_IS_BYREF | PTFF_R5_IS_GCREF | PTFF_R5_IS_BYREF)) >> 31); - ASSERT((returnKind == GCRK_Scalar) || ((transFrameFlags & PTFF_SAVE_R4) && (transFrameFlags & PTFF_SAVE_R5))); - return returnKind; -} - -#elif defined(TARGET_AMD64) - -// Verify that we can use bitwise shifts to convert from GCRefKind to PInvokeTransitionFrameFlags and back -C_ASSERT(PTFF_RAX_IS_GCREF == ((uint64_t)GCRK_Object << 16)); -C_ASSERT(PTFF_RAX_IS_BYREF == ((uint64_t)GCRK_Byref << 16)); -C_ASSERT(PTFF_RDX_IS_GCREF == ((uint64_t)GCRK_Scalar_Obj << 16)); -C_ASSERT(PTFF_RDX_IS_BYREF == ((uint64_t)GCRK_Scalar_Byref << 16)); - -inline uint64_t ReturnKindToTransitionFrameFlags(GCRefKind returnKind) -{ - // just need to report gc ref bits here. - // appropriate PTFF_SAVE_ bits will be added by the frame building routine. - return ((uint64_t)returnKind << 16); -} - -inline GCRefKind TransitionFrameFlagsToReturnKind(uint64_t transFrameFlags) -{ - GCRefKind returnKind = (GCRefKind)((transFrameFlags & (PTFF_RAX_IS_GCREF | PTFF_RAX_IS_BYREF | PTFF_RDX_IS_GCREF | PTFF_RDX_IS_BYREF)) >> 16); -#if defined(TARGET_UNIX) - ASSERT((returnKind == GCRK_Scalar) || ((transFrameFlags & PTFF_SAVE_RAX) && (transFrameFlags & PTFF_SAVE_RDX))); -#else - ASSERT((returnKind == GCRK_Scalar) || (transFrameFlags & PTFF_SAVE_RAX)); -#endif - return returnKind; -} - -#elif defined(TARGET_X86) - +#if defined(TARGET_X86) // Verify that we can use bitwise shifts to convert from GCRefKind to PInvokeTransitionFrameFlags and back C_ASSERT(PTFF_RAX_IS_GCREF == ((uint64_t)GCRK_Object << 16)); C_ASSERT(PTFF_RAX_IS_BYREF == ((uint64_t)GCRK_Byref << 16)); @@ -132,40 +51,13 @@ inline GCRefKind TransitionFrameFlagsToReturnKind(uintptr_t transFrameFlags) return returnKind; } -#elif defined(TARGET_ARM) - -// Verify that we can use bitwise shifts to convert from GCRefKind to PInvokeTransitionFrameFlags and back -C_ASSERT(PTFF_R0_IS_GCREF == ((uint64_t)GCRK_Object << 14)); -C_ASSERT(PTFF_R0_IS_BYREF == ((uint64_t)GCRK_Byref << 14)); - -inline uint64_t ReturnKindToTransitionFrameFlags(GCRefKind returnKind) -{ - // just need to report gc ref bits here. - // appropriate PTFF_SAVE_ bits will be added by the frame building routine. - return ((uint64_t)returnKind << 14); -} - -inline GCRefKind TransitionFrameFlagsToReturnKind(uint64_t transFrameFlags) -{ - GCRefKind returnKind = (GCRefKind)((transFrameFlags & (PTFF_R0_IS_GCREF | PTFF_R0_IS_BYREF)) >> 14); - ASSERT((returnKind == GCRK_Scalar) || (transFrameFlags & PTFF_SAVE_R0)); - return returnKind; -} - -#endif - // Extract individual GCRefKind components from a composite return kind -inline GCRefKind ExtractReg0ReturnKind(GCRefKind returnKind) +inline GCRefKind ExtractReturnKind(GCRefKind returnKind) { ASSERT(returnKind <= GCRK_LastValid); return (GCRefKind)(returnKind & (GCRK_Object | GCRK_Byref)); } - -inline GCRefKind ExtractReg1ReturnKind(GCRefKind returnKind) -{ - ASSERT(returnKind <= GCRK_LastValid); - return (GCRefKind)(returnKind >> 2); -} +#endif // // MethodInfo is placeholder type used to allocate space for MethodInfo. Maximum size @@ -272,9 +164,14 @@ class ICodeManager virtual bool IsUnwindable(PTR_VOID pvAddress) PURE_VIRTUAL virtual bool GetReturnAddressHijackInfo(MethodInfo * pMethodInfo, - REGDISPLAY * pRegisterSet, // in - PTR_PTR_VOID * ppvRetAddrLocation, // out - GCRefKind * pRetValueKind) PURE_VIRTUAL // out + REGDISPLAY * pRegisterSet, // in + PTR_PTR_VOID * ppvRetAddrLocation // out + ) PURE_VIRTUAL + +#ifdef TARGET_X86 + virtual GCRefKind GetReturnValueKind(MethodInfo * pMethodInfo, + REGDISPLAY * pRegisterSet) PURE_VIRTUAL +#endif virtual PTR_VOID RemapHardwareFaultToGCSafePoint(MethodInfo * pMethodInfo, PTR_VOID controlPC) PURE_VIRTUAL diff --git a/src/coreclr/nativeaot/Runtime/StackFrameIterator.cpp b/src/coreclr/nativeaot/Runtime/StackFrameIterator.cpp index f2f208c89174c1..fab1a9b6f66188 100644 --- a/src/coreclr/nativeaot/Runtime/StackFrameIterator.cpp +++ b/src/coreclr/nativeaot/Runtime/StackFrameIterator.cpp @@ -77,10 +77,18 @@ StackFrameIterator::StackFrameIterator(Thread * pThreadToWalk, PInvokeTransition { InternalInit(pThreadToWalk, pThreadToWalk->GetInterruptedContext(), GcStackWalkFlags | ActiveStackFrame); } - else + else if (pInitialTransitionFrame == TOP_OF_STACK_MARKER) { InternalInit(pThreadToWalk, pInitialTransitionFrame, GcStackWalkFlags); } + else + { + uint32_t flags = (pInitialTransitionFrame->m_Flags & PTFF_THREAD_HIJACK) == 0 ? + GcStackWalkFlags : + GcStackWalkFlags | ActiveStackFrame; + + InternalInit(pThreadToWalk, pInitialTransitionFrame, flags); + } PrepareToYieldFrame(); } @@ -110,8 +118,10 @@ void StackFrameIterator::EnterInitialInvalidState(Thread * pThreadToWalk) m_pThread = pThreadToWalk; m_pInstance = GetRuntimeInstance(); m_pCodeManager = NULL; +#ifdef TARGET_X86 m_pHijackedReturnValue = NULL; m_HijackedReturnValueKind = GCRK_Unknown; +#endif m_pConservativeStackRangeLowerBound = NULL; m_pConservativeStackRangeUpperBound = NULL; m_pendingFuncletFramePointer = NULL; @@ -180,17 +190,6 @@ void StackFrameIterator::InternalInit(Thread * pThreadToWalk, PInvokeTransitionF if (pFrame->m_Flags & PTFF_SAVE_R3) { m_RegDisplay.pR3 = pPreservedRegsCursor++; } if (pFrame->m_Flags & PTFF_SAVE_LR) { m_RegDisplay.pLR = pPreservedRegsCursor++; } - if (pFrame->m_Flags & PTFF_R0_IS_GCREF) - { - m_pHijackedReturnValue = (PTR_OBJECTREF) m_RegDisplay.pR0; - m_HijackedReturnValueKind = GCRK_Object; - } - if (pFrame->m_Flags & PTFF_R0_IS_BYREF) - { - m_pHijackedReturnValue = (PTR_OBJECTREF) m_RegDisplay.pR0; - m_HijackedReturnValueKind = GCRK_Byref; - } - #elif defined(TARGET_ARM64) m_RegDisplay.pFP = (PTR_uintptr_t)PTR_HOST_MEMBER_TADDR(PInvokeTransitionFrame, pFrame, m_FramePointer); m_RegDisplay.pLR = (PTR_uintptr_t)PTR_HOST_MEMBER_TADDR(PInvokeTransitionFrame, pFrame, m_RIP); @@ -232,13 +231,6 @@ void StackFrameIterator::InternalInit(Thread * pThreadToWalk, PInvokeTransitionF if (pFrame->m_Flags & PTFF_SAVE_LR) { m_RegDisplay.pLR = pPreservedRegsCursor++; } - GCRefKind retValueKind = TransitionFrameFlagsToReturnKind(pFrame->m_Flags); - if (retValueKind != GCRK_Scalar) - { - m_pHijackedReturnValue = (PTR_OBJECTREF)m_RegDisplay.pX0; - m_HijackedReturnValueKind = retValueKind; - } - #elif defined(TARGET_LOONGARCH64) m_RegDisplay.pFP = (PTR_uintptr_t)PTR_HOST_MEMBER_TADDR(PInvokeTransitionFrame, pFrame, m_FramePointer); m_RegDisplay.pRA = (PTR_uintptr_t)PTR_HOST_MEMBER_TADDR(PInvokeTransitionFrame, pFrame, m_RIP); @@ -280,13 +272,6 @@ void StackFrameIterator::InternalInit(Thread * pThreadToWalk, PInvokeTransitionF if (pFrame->m_Flags & PTFF_SAVE_RA) { m_RegDisplay.pRA = pPreservedRegsCursor++; } - GCRefKind retValueKind = TransitionFrameFlagsToReturnKind(pFrame->m_Flags); - if (retValueKind != GCRK_Scalar) - { - m_pHijackedReturnValue = (PTR_OBJECTREF)m_RegDisplay.pR4; - m_HijackedReturnValueKind = retValueKind; - } - #else // TARGET_ARM if (pFrame->m_Flags & PTFF_SAVE_RBX) { m_RegDisplay.pRbx = pPreservedRegsCursor++; } if (pFrame->m_Flags & PTFF_SAVE_RSI) { m_RegDisplay.pRsi = pPreservedRegsCursor++; } @@ -314,12 +299,14 @@ void StackFrameIterator::InternalInit(Thread * pThreadToWalk, PInvokeTransitionF if (pFrame->m_Flags & PTFF_SAVE_R11) { m_RegDisplay.pR11 = pPreservedRegsCursor++; } #endif // TARGET_AMD64 +#ifdef TARGET_X86 GCRefKind retValueKind = TransitionFrameFlagsToReturnKind(pFrame->m_Flags); if (retValueKind != GCRK_Scalar) { m_pHijackedReturnValue = (PTR_OBJECTREF)m_RegDisplay.pRax; m_HijackedReturnValueKind = retValueKind; } +#endif #endif // TARGET_ARM @@ -1529,8 +1516,10 @@ void StackFrameIterator::NextInternal() m_dwFlags &= ~(ExCollide|MethodStateCalculated|UnwoundReversePInvoke|ActiveStackFrame); ASSERT(IsValid()); +#ifdef TARGET_X86 m_pHijackedReturnValue = NULL; m_HijackedReturnValueKind = GCRK_Unknown; +#endif #ifdef _DEBUG SetControlPC(dac_cast((void*)666)); @@ -1944,6 +1933,7 @@ void StackFrameIterator::CalculateCurrentMethodState() m_dwFlags |= MethodStateCalculated; } +#ifdef TARGET_X86 bool StackFrameIterator::GetHijackedReturnValueLocation(PTR_OBJECTREF * pLocation, GCRefKind * pKind) { if (GCRK_Unknown == m_HijackedReturnValueKind) @@ -1955,6 +1945,7 @@ bool StackFrameIterator::GetHijackedReturnValueLocation(PTR_OBJECTREF * pLocatio *pKind = m_HijackedReturnValueKind; return true; } +#endif void StackFrameIterator::SetControlPC(PTR_VOID controlPC) { diff --git a/src/coreclr/nativeaot/Runtime/StackFrameIterator.h b/src/coreclr/nativeaot/Runtime/StackFrameIterator.h index f174edd4c473b2..c3fecb9f84e29e 100644 --- a/src/coreclr/nativeaot/Runtime/StackFrameIterator.h +++ b/src/coreclr/nativeaot/Runtime/StackFrameIterator.h @@ -51,7 +51,9 @@ class StackFrameIterator PTR_ICodeManager GetCodeManager(); MethodInfo * GetMethodInfo(); bool IsActiveStackFrame(); +#ifdef TARGET_X86 bool GetHijackedReturnValueLocation(PTR_OBJECTREF * pLocation, GCRefKind * pKind); +#endif void SetControlPC(PTR_VOID controlPC); static bool IsValidReturnAddress(PTR_VOID pvAddress); @@ -221,10 +223,12 @@ class StackFrameIterator PTR_ICodeManager m_pCodeManager; MethodInfo m_methodInfo; PTR_VOID m_effectiveSafePointAddress; +#ifdef TARGET_X86 PTR_OBJECTREF m_pHijackedReturnValue; GCRefKind m_HijackedReturnValueKind; - PTR_uintptr_t m_pConservativeStackRangeLowerBound; - PTR_uintptr_t m_pConservativeStackRangeUpperBound; +#endif + PTR_uintptr_t m_pConservativeStackRangeLowerBound; + PTR_uintptr_t m_pConservativeStackRangeUpperBound; uint32_t m_dwFlags; PTR_ExInfo m_pNextExInfo; PTR_VOID m_pendingFuncletFramePointer; diff --git a/src/coreclr/nativeaot/Runtime/amd64/AsmMacros.inc b/src/coreclr/nativeaot/Runtime/amd64/AsmMacros.inc index 41c43252317d9a..4a3437f2f0618b 100644 --- a/src/coreclr/nativeaot/Runtime/amd64/AsmMacros.inc +++ b/src/coreclr/nativeaot/Runtime/amd64/AsmMacros.inc @@ -356,9 +356,8 @@ PTFF_SAVE_ALL_PRESERVED equ 000000F7h ;; NOTE: RBP is not included in this set PTFF_SAVE_RSP equ 00008000h PTFF_SAVE_RAX equ 00000100h ;; RAX is saved in hijack handler - in case it contains a GC ref PTFF_SAVE_ALL_SCRATCH equ 00007F00h -PTFF_RAX_IS_GCREF equ 00010000h ;; iff PTFF_SAVE_RAX: set -> eax is Object, clear -> eax is scalar -PTFF_RAX_IS_BYREF equ 00020000h ;; iff PTFF_SAVE_RAX: set -> eax is ByRef, clear -> eax is Object or scalar PTFF_THREAD_ABORT equ 00100000h ;; indicates that ThreadAbortException should be thrown when returning from the transition +PTFF_THREAD_HIJACK equ 00200000h ;; indicates that this is a frame for a hijacked call ;; These must match the TrapThreadsFlags enum TrapThreadsFlags_None equ 0 diff --git a/src/coreclr/nativeaot/Runtime/amd64/AsmOffsetsCpu.h b/src/coreclr/nativeaot/Runtime/amd64/AsmOffsetsCpu.h index 2a2e85e5e72baa..afeb2a408851a4 100644 --- a/src/coreclr/nativeaot/Runtime/amd64/AsmOffsetsCpu.h +++ b/src/coreclr/nativeaot/Runtime/amd64/AsmOffsetsCpu.h @@ -8,7 +8,7 @@ // NOTE: the offsets MUST be in hex notation WITHOUT the 0x prefix #ifndef UNIX_AMD64_ABI -PLAT_ASM_SIZEOF(260, ExInfo) +PLAT_ASM_SIZEOF(250, ExInfo) PLAT_ASM_OFFSET(0, ExInfo, m_pPrevExInfo) PLAT_ASM_OFFSET(8, ExInfo, m_pExContext) PLAT_ASM_OFFSET(10, ExInfo, m_exception) @@ -16,7 +16,7 @@ PLAT_ASM_OFFSET(18, ExInfo, m_kind) PLAT_ASM_OFFSET(19, ExInfo, m_passNumber) PLAT_ASM_OFFSET(1c, ExInfo, m_idxCurClause) PLAT_ASM_OFFSET(20, ExInfo, m_frameIter) -PLAT_ASM_OFFSET(250, ExInfo, m_notifyDebuggerSP) +PLAT_ASM_OFFSET(240, ExInfo, m_notifyDebuggerSP) PLAT_ASM_OFFSET(0, PInvokeTransitionFrame, m_RIP) PLAT_ASM_OFFSET(8, PInvokeTransitionFrame, m_FramePointer) @@ -24,12 +24,12 @@ PLAT_ASM_OFFSET(10, PInvokeTransitionFrame, m_pThread) PLAT_ASM_OFFSET(18, PInvokeTransitionFrame, m_Flags) PLAT_ASM_OFFSET(20, PInvokeTransitionFrame, m_PreservedRegs) -PLAT_ASM_SIZEOF(230, StackFrameIterator) +PLAT_ASM_SIZEOF(220, StackFrameIterator) PLAT_ASM_OFFSET(10, StackFrameIterator, m_FramePointer) PLAT_ASM_OFFSET(18, StackFrameIterator, m_ControlPC) PLAT_ASM_OFFSET(20, StackFrameIterator, m_RegDisplay) -PLAT_ASM_OFFSET(220, StackFrameIterator, m_OriginalControlPC) -PLAT_ASM_OFFSET(228, StackFrameIterator, m_pPreviousTransitionFrame) +PLAT_ASM_OFFSET(210, StackFrameIterator, m_OriginalControlPC) +PLAT_ASM_OFFSET(218, StackFrameIterator, m_pPreviousTransitionFrame) PLAT_ASM_SIZEOF(100, PAL_LIMITED_CONTEXT) PLAT_ASM_OFFSET(0, PAL_LIMITED_CONTEXT, IP) @@ -73,7 +73,7 @@ PLAT_ASM_OFFSET(90, REGDISPLAY, Xmm) #else // !UNIX_AMD64_ABI -PLAT_ASM_SIZEOF(1a0, ExInfo) +PLAT_ASM_SIZEOF(190, ExInfo) PLAT_ASM_OFFSET(0, ExInfo, m_pPrevExInfo) PLAT_ASM_OFFSET(8, ExInfo, m_pExContext) PLAT_ASM_OFFSET(10, ExInfo, m_exception) @@ -81,7 +81,7 @@ PLAT_ASM_OFFSET(18, ExInfo, m_kind) PLAT_ASM_OFFSET(19, ExInfo, m_passNumber) PLAT_ASM_OFFSET(1c, ExInfo, m_idxCurClause) PLAT_ASM_OFFSET(20, ExInfo, m_frameIter) -PLAT_ASM_OFFSET(198, ExInfo, m_notifyDebuggerSP) +PLAT_ASM_OFFSET(188, ExInfo, m_notifyDebuggerSP) PLAT_ASM_OFFSET(0, PInvokeTransitionFrame, m_RIP) PLAT_ASM_OFFSET(8, PInvokeTransitionFrame, m_FramePointer) @@ -89,12 +89,12 @@ PLAT_ASM_OFFSET(10, PInvokeTransitionFrame, m_pThread) PLAT_ASM_OFFSET(18, PInvokeTransitionFrame, m_Flags) PLAT_ASM_OFFSET(20, PInvokeTransitionFrame, m_PreservedRegs) -PLAT_ASM_SIZEOF(178, StackFrameIterator) +PLAT_ASM_SIZEOF(168, StackFrameIterator) PLAT_ASM_OFFSET(10, StackFrameIterator, m_FramePointer) PLAT_ASM_OFFSET(18, StackFrameIterator, m_ControlPC) PLAT_ASM_OFFSET(20, StackFrameIterator, m_RegDisplay) -PLAT_ASM_OFFSET(168, StackFrameIterator, m_OriginalControlPC) -PLAT_ASM_OFFSET(170, StackFrameIterator, m_pPreviousTransitionFrame) +PLAT_ASM_OFFSET(158, StackFrameIterator, m_OriginalControlPC) +PLAT_ASM_OFFSET(160, StackFrameIterator, m_pPreviousTransitionFrame) PLAT_ASM_SIZEOF(50, PAL_LIMITED_CONTEXT) PLAT_ASM_OFFSET(0, PAL_LIMITED_CONTEXT, IP) diff --git a/src/coreclr/nativeaot/Runtime/amd64/GcProbe.S b/src/coreclr/nativeaot/Runtime/amd64/GcProbe.S index d8a08e76f4588c..ef4709055f0101 100644 --- a/src/coreclr/nativeaot/Runtime/amd64/GcProbe.S +++ b/src/coreclr/nativeaot/Runtime/amd64/GcProbe.S @@ -76,7 +76,6 @@ // // Register state on exit: // R11: thread pointer -// RCX: return value flags // RAX, RDX preserved, other volatile regs trashed // .macro FixupHijackedCallstack @@ -95,14 +94,10 @@ mov rcx, [r11 + OFFSETOF__Thread__m_pvHijackedReturnAddress] push rcx - // Fetch the return address flags - mov rcx, [r11 + OFFSETOF__Thread__m_uHijackedReturnValueFlags] - // Clear hijack state - xor r9, r9 - mov [r11 + OFFSETOF__Thread__m_ppvHijackedReturnAddressLocation], r9 - mov [r11 + OFFSETOF__Thread__m_pvHijackedReturnAddress], r9 - mov [r11 + OFFSETOF__Thread__m_uHijackedReturnValueFlags], r9 + xor ecx, ecx + mov [r11 + OFFSETOF__Thread__m_ppvHijackedReturnAddressLocation], rcx + mov [r11 + OFFSETOF__Thread__m_pvHijackedReturnAddress], rcx .endm // @@ -117,7 +112,7 @@ NESTED_ENTRY RhpGcProbeHijack, _TEXT, NoHandler ret LOCAL_LABEL(WaitForGC): - or ecx, DEFAULT_FRAME_SAVE_FLAGS + PTFF_SAVE_RAX + PTFF_SAVE_RDX + mov ecx, DEFAULT_FRAME_SAVE_FLAGS + PTFF_SAVE_RAX + PTFF_SAVE_RDX + PTFF_THREAD_HIJACK jmp C_FUNC(RhpWaitForGC) NESTED_END RhpGcProbeHijack, _TEXT diff --git a/src/coreclr/nativeaot/Runtime/amd64/GcProbe.asm b/src/coreclr/nativeaot/Runtime/amd64/GcProbe.asm index 531762eedd8da4..7410d851d5a1c4 100644 --- a/src/coreclr/nativeaot/Runtime/amd64/GcProbe.asm +++ b/src/coreclr/nativeaot/Runtime/amd64/GcProbe.asm @@ -76,7 +76,6 @@ endm ;; ;; Register state on exit: ;; RDX: thread pointer -;; RCX: return value flags ;; RAX: preserved, other volatile regs trashed ;; FixupHijackedCallstack macro @@ -87,14 +86,10 @@ FixupHijackedCallstack macro mov rcx, [rdx + OFFSETOF__Thread__m_pvHijackedReturnAddress] push rcx - ;; Fetch the return address flags - mov rcx, [rdx + OFFSETOF__Thread__m_uHijackedReturnValueFlags] - ;; Clear hijack state - xor r9, r9 - mov [rdx + OFFSETOF__Thread__m_ppvHijackedReturnAddressLocation], r9 - mov [rdx + OFFSETOF__Thread__m_pvHijackedReturnAddress], r9 - mov [rdx + OFFSETOF__Thread__m_uHijackedReturnValueFlags], r9 + xor ecx, ecx + mov [rdx + OFFSETOF__Thread__m_ppvHijackedReturnAddressLocation], rcx + mov [rdx + OFFSETOF__Thread__m_pvHijackedReturnAddress], rcx endm EXTERN RhpPInvokeExceptionGuard : PROC @@ -110,7 +105,7 @@ NESTED_ENTRY RhpGcProbeHijack, _TEXT, RhpPInvokeExceptionGuard jnz @f ret @@: - or ecx, DEFAULT_FRAME_SAVE_FLAGS + PTFF_SAVE_RAX + mov ecx, DEFAULT_FRAME_SAVE_FLAGS + PTFF_SAVE_RAX + PTFF_THREAD_HIJACK jmp RhpWaitForGC NESTED_END RhpGcProbeHijack, _TEXT diff --git a/src/coreclr/nativeaot/Runtime/arm/AsmOffsetsCpu.h b/src/coreclr/nativeaot/Runtime/arm/AsmOffsetsCpu.h index ab5b991274b421..5e7a0203df889b 100644 --- a/src/coreclr/nativeaot/Runtime/arm/AsmOffsetsCpu.h +++ b/src/coreclr/nativeaot/Runtime/arm/AsmOffsetsCpu.h @@ -7,7 +7,7 @@ // // NOTE: the offsets MUST be in hex notation WITHOUT the 0x prefix -PLAT_ASM_SIZEOF(130, ExInfo) +PLAT_ASM_SIZEOF(128, ExInfo) PLAT_ASM_OFFSET(0, ExInfo, m_pPrevExInfo) PLAT_ASM_OFFSET(4, ExInfo, m_pExContext) PLAT_ASM_OFFSET(8, ExInfo, m_exception) @@ -15,7 +15,7 @@ PLAT_ASM_OFFSET(0c, ExInfo, m_kind) PLAT_ASM_OFFSET(0d, ExInfo, m_passNumber) PLAT_ASM_OFFSET(10, ExInfo, m_idxCurClause) PLAT_ASM_OFFSET(18, ExInfo, m_frameIter) -PLAT_ASM_OFFSET(128, ExInfo, m_notifyDebuggerSP) +PLAT_ASM_OFFSET(120, ExInfo, m_notifyDebuggerSP) PLAT_ASM_OFFSET(0, PInvokeTransitionFrame, m_FramePointer) PLAT_ASM_OFFSET(4, PInvokeTransitionFrame, m_RIP) @@ -23,12 +23,12 @@ PLAT_ASM_OFFSET(8, PInvokeTransitionFrame, m_pThread) PLAT_ASM_OFFSET(c, PInvokeTransitionFrame, m_Flags) PLAT_ASM_OFFSET(10, PInvokeTransitionFrame, m_PreservedRegs) -PLAT_ASM_SIZEOF(110, StackFrameIterator) +PLAT_ASM_SIZEOF(108, StackFrameIterator) PLAT_ASM_OFFSET(08, StackFrameIterator, m_FramePointer) PLAT_ASM_OFFSET(0c, StackFrameIterator, m_ControlPC) PLAT_ASM_OFFSET(10, StackFrameIterator, m_RegDisplay) -PLAT_ASM_OFFSET(108, StackFrameIterator, m_OriginalControlPC) -PLAT_ASM_OFFSET(10c, StackFrameIterator, m_pPreviousTransitionFrame) +PLAT_ASM_OFFSET(100, StackFrameIterator, m_OriginalControlPC) +PLAT_ASM_OFFSET(104, StackFrameIterator, m_pPreviousTransitionFrame) PLAT_ASM_SIZEOF(70, PAL_LIMITED_CONTEXT) PLAT_ASM_OFFSET(24, PAL_LIMITED_CONTEXT, IP) diff --git a/src/coreclr/nativeaot/Runtime/arm/GcProbe.S b/src/coreclr/nativeaot/Runtime/arm/GcProbe.S index 8277d9035b0d05..0092be687bcec5 100644 --- a/src/coreclr/nativeaot/Runtime/arm/GcProbe.S +++ b/src/coreclr/nativeaot/Runtime/arm/GcProbe.S @@ -75,13 +75,11 @@ // Fix the stack by restoring the original return address ldr lr, [r2, #OFFSETOF__Thread__m_pvHijackedReturnAddress] - ldr r12, [r2, #OFFSETOF__Thread__m_uHijackedReturnValueFlags] // Clear hijack state mov r3, #0 str r3, [r2, #OFFSETOF__Thread__m_ppvHijackedReturnAddressLocation] str r3, [r2, #OFFSETOF__Thread__m_pvHijackedReturnAddress] - str r3, [r2, #OFFSETOF__Thread__m_uHijackedReturnValueFlags] .endm NESTED_ENTRY RhpWaitForGC, _TEXT, NoHandler @@ -126,8 +124,8 @@ NESTED_ENTRY RhpGcProbeHijack, _TEXT, NoHandler bne LOCAL_LABEL(WaitForGC) bx lr LOCAL_LABEL(WaitForGC): - mov r3, #(DEFAULT_FRAME_SAVE_FLAGS + PTFF_SAVE_R0) - orr r12, r3 + mov r12, #(DEFAULT_FRAME_SAVE_FLAGS + PTFF_SAVE_R0) + orr r12, r12, #PTFF_THREAD_HIJACK b RhpWaitForGC NESTED_END RhpGcProbeHijack diff --git a/src/coreclr/nativeaot/Runtime/arm64/AsmMacros.h b/src/coreclr/nativeaot/Runtime/arm64/AsmMacros.h index 2f6e83e2cf9b66..90e1b5d7779947 100644 --- a/src/coreclr/nativeaot/Runtime/arm64/AsmMacros.h +++ b/src/coreclr/nativeaot/Runtime/arm64/AsmMacros.h @@ -60,17 +60,10 @@ PTFF_SAVE_ALL_SCRATCH equ 0x3FFFF800 ;; NOTE: X0-X18 PTFF_SAVE_FP equ 0x40000000 PTFF_SAVE_LR equ 0x80000000 -;; NOTE: The following flags represent the upper 32 bits of the PInvokeTransitionFrameFlags. -;; Since the assembler doesn't support 64 bit constants in any way, we need to define just -;; the upper bits here -PTFF_X0_IS_GCREF_HI equ 0x00000001 ;; iff PTFF_SAVE_X0 : set->x0 is Object, clear->x0 is scalar -PTFF_X0_IS_BYREF_HI equ 0x00000002 ;; iff PTFF_SAVE_X0 : set->x0 is ByRef, clear->x0 is Object or scalar -PTFF_X1_IS_GCREF_HI equ 0x00000004 ;; iff PTFF_SAVE_X1 : set->x1 is Object, clear->x1 is scalar -PTFF_X1_IS_BYREF_HI equ 0x00000008 ;; iff PTFF_SAVE_X1 : set->x1 is ByRef, clear->x1 is Object or scalar -PTFF_THREAD_ABORT_HI equ 0x00000010 ;; indicates that ThreadAbortException should be thrown when returning from the transition +PTFF_THREAD_HIJACK_HI equ 0x00000002 // upper 32 bits of the PTFF_THREAD_HIJACK ;; Bit position for the flags above, to be used with tbz / tbnz instructions -PTFF_THREAD_ABORT_BIT equ 36 +PTFF_THREAD_ABORT_BIT equ 32 ;; These must match the TrapThreadsFlags enum TrapThreadsFlags_None equ 0 diff --git a/src/coreclr/nativeaot/Runtime/arm64/AsmOffsetsCpu.h b/src/coreclr/nativeaot/Runtime/arm64/AsmOffsetsCpu.h index 193692feae810a..62c34004d7613b 100644 --- a/src/coreclr/nativeaot/Runtime/arm64/AsmOffsetsCpu.h +++ b/src/coreclr/nativeaot/Runtime/arm64/AsmOffsetsCpu.h @@ -7,7 +7,7 @@ // // NOTE: the offsets MUST be in hex notation WITHOUT the 0x prefix -PLAT_ASM_SIZEOF(288, ExInfo) +PLAT_ASM_SIZEOF(278, ExInfo) PLAT_ASM_OFFSET(0, ExInfo, m_pPrevExInfo) PLAT_ASM_OFFSET(8, ExInfo, m_pExContext) PLAT_ASM_OFFSET(10, ExInfo, m_exception) @@ -15,7 +15,7 @@ PLAT_ASM_OFFSET(18, ExInfo, m_kind) PLAT_ASM_OFFSET(19, ExInfo, m_passNumber) PLAT_ASM_OFFSET(1c, ExInfo, m_idxCurClause) PLAT_ASM_OFFSET(20, ExInfo, m_frameIter) -PLAT_ASM_OFFSET(280, ExInfo, m_notifyDebuggerSP) +PLAT_ASM_OFFSET(270, ExInfo, m_notifyDebuggerSP) PLAT_ASM_OFFSET(0, PInvokeTransitionFrame, m_FramePointer) PLAT_ASM_OFFSET(8, PInvokeTransitionFrame, m_RIP) @@ -23,12 +23,12 @@ PLAT_ASM_OFFSET(10, PInvokeTransitionFrame, m_pThread) PLAT_ASM_OFFSET(18, PInvokeTransitionFrame, m_Flags) PLAT_ASM_OFFSET(20, PInvokeTransitionFrame, m_PreservedRegs) -PLAT_ASM_SIZEOF(260, StackFrameIterator) +PLAT_ASM_SIZEOF(250, StackFrameIterator) PLAT_ASM_OFFSET(10, StackFrameIterator, m_FramePointer) PLAT_ASM_OFFSET(18, StackFrameIterator, m_ControlPC) PLAT_ASM_OFFSET(20, StackFrameIterator, m_RegDisplay) -PLAT_ASM_OFFSET(250, StackFrameIterator, m_OriginalControlPC) -PLAT_ASM_OFFSET(258, StackFrameIterator, m_pPreviousTransitionFrame) +PLAT_ASM_OFFSET(240, StackFrameIterator, m_OriginalControlPC) +PLAT_ASM_OFFSET(248, StackFrameIterator, m_pPreviousTransitionFrame) PLAT_ASM_SIZEOF(C0, PAL_LIMITED_CONTEXT) diff --git a/src/coreclr/nativeaot/Runtime/arm64/GcProbe.S b/src/coreclr/nativeaot/Runtime/arm64/GcProbe.S index 0a1b71eeae738f..b8ae78630a6eab 100644 --- a/src/coreclr/nativeaot/Runtime/arm64/GcProbe.S +++ b/src/coreclr/nativeaot/Runtime/arm64/GcProbe.S @@ -93,7 +93,6 @@ // // Register state on exit: // x2: thread pointer -// x12: transition frame flags for the return registers x0 and x1 // .macro FixupHijackedCallstack @@ -107,17 +106,13 @@ // // Fix the stack by restoring the original return address // - // Load m_pvHijackedReturnAddress and m_uHijackedReturnValueFlags - ldp lr, x12, [x2, #OFFSETOF__Thread__m_pvHijackedReturnAddress] + ldr lr, [x2, #OFFSETOF__Thread__m_pvHijackedReturnAddress] // // Clear hijack state // // Clear m_ppvHijackedReturnAddressLocation and m_pvHijackedReturnAddress stp xzr, xzr, [x2, #OFFSETOF__Thread__m_ppvHijackedReturnAddressLocation] - // Clear m_uHijackedReturnValueFlags - str xzr, [x2, #OFFSETOF__Thread__m_uHijackedReturnValueFlags] - .endm // @@ -131,7 +126,8 @@ NESTED_ENTRY RhpGcProbeHijack, _TEXT, NoHandler ret LOCAL_LABEL(WaitForGC): - orr x12, x12, DEFAULT_FRAME_SAVE_FLAGS + PTFF_SAVE_X0 + PTFF_SAVE_X1 + mov x12, DEFAULT_FRAME_SAVE_FLAGS + PTFF_SAVE_X0 + PTFF_SAVE_X1 + movk x12, PTFF_THREAD_HIJACK_HI, lsl #32 b C_FUNC(RhpWaitForGC) NESTED_END RhpGcProbeHijack diff --git a/src/coreclr/nativeaot/Runtime/arm64/GcProbe.asm b/src/coreclr/nativeaot/Runtime/arm64/GcProbe.asm index 12de9d9fe9a1da..b9048873ea6dea 100644 --- a/src/coreclr/nativeaot/Runtime/arm64/GcProbe.asm +++ b/src/coreclr/nativeaot/Runtime/arm64/GcProbe.asm @@ -105,7 +105,6 @@ PROBE_FRAME_SIZE field 0 ;; Register state on exit: ;; x2: thread pointer ;; x3: trashed -;; x12: transition frame flags for the return registers x0 and x1 ;; MACRO FixupHijackedCallstack @@ -116,9 +115,7 @@ PROBE_FRAME_SIZE field 0 ;; ;; Fix the stack by restoring the original return address ;; - ASSERT OFFSETOF__Thread__m_uHijackedReturnValueFlags == (OFFSETOF__Thread__m_pvHijackedReturnAddress + 8) - ;; Load m_pvHijackedReturnAddress and m_uHijackedReturnValueFlags - ldp lr, x12, [x2, #OFFSETOF__Thread__m_pvHijackedReturnAddress] + ldr lr, [x2, #OFFSETOF__Thread__m_pvHijackedReturnAddress] ;; ;; Clear hijack state @@ -126,9 +123,6 @@ PROBE_FRAME_SIZE field 0 ASSERT OFFSETOF__Thread__m_pvHijackedReturnAddress == (OFFSETOF__Thread__m_ppvHijackedReturnAddressLocation + 8) ;; Clear m_ppvHijackedReturnAddressLocation and m_pvHijackedReturnAddress stp xzr, xzr, [x2, #OFFSETOF__Thread__m_ppvHijackedReturnAddressLocation] - ;; Clear m_uHijackedReturnValueFlags - str xzr, [x2, #OFFSETOF__Thread__m_uHijackedReturnValueFlags] - MEND MACRO @@ -161,7 +155,8 @@ PROBE_FRAME_SIZE field 0 ret WaitForGC - orr x12, x12, #(DEFAULT_FRAME_SAVE_FLAGS + PTFF_SAVE_X0 + PTFF_SAVE_X1) + mov x12, #(DEFAULT_FRAME_SAVE_FLAGS + PTFF_SAVE_X0 + PTFF_SAVE_X1) + movk x12, #PTFF_THREAD_HIJACK_HI, lsl #32 b RhpWaitForGC NESTED_END RhpGcProbeHijackWrapper diff --git a/src/coreclr/nativeaot/Runtime/i386/AsmMacros.inc b/src/coreclr/nativeaot/Runtime/i386/AsmMacros.inc index 9541f73940215a..8ee2e79f44fde0 100644 --- a/src/coreclr/nativeaot/Runtime/i386/AsmMacros.inc +++ b/src/coreclr/nativeaot/Runtime/i386/AsmMacros.inc @@ -125,8 +125,6 @@ PTFF_SAVE_ALL_PRESERVED equ 00000007h ;; NOTE: RBP is not included in this set PTFF_SAVE_RSP equ 00008000h PTFF_SAVE_RAX equ 00000100h ;; RAX is saved if it contains a GC ref and we're in hijack handler PTFF_SAVE_ALL_SCRATCH equ 00000700h -PTFF_RAX_IS_GCREF equ 00010000h ;; iff PTFF_SAVE_RAX: set -> eax is Object, clear -> eax is scalar -PTFF_RAX_IS_BYREF equ 00020000h ;; iff PTFF_SAVE_RAX: set -> eax is ByRef, clear -> eax is Object or scalar PTFF_THREAD_ABORT equ 00100000h ;; indicates that ThreadAbortException should be thrown when returning from the transition ;; These must match the TrapThreadsFlags enum diff --git a/src/coreclr/nativeaot/Runtime/inc/rhbinder.h b/src/coreclr/nativeaot/Runtime/inc/rhbinder.h index 21a15a01c905e4..84f10d2257ea57 100644 --- a/src/coreclr/nativeaot/Runtime/inc/rhbinder.h +++ b/src/coreclr/nativeaot/Runtime/inc/rhbinder.h @@ -271,10 +271,9 @@ enum PInvokeTransitionFrameFlags // a return address pointing into the hijacked method and that method's // lr register, which may hold a gc pointer - PTFF_R0_IS_GCREF = 0x00004000, // used by hijack handler to report return value of hijacked method - PTFF_R0_IS_BYREF = 0x00008000, // used by hijack handler to report return value of hijacked method + PTFF_THREAD_ABORT = 0x00004000, // indicates that ThreadAbortException should be thrown when returning from the transition - PTFF_THREAD_ABORT = 0x00010000, // indicates that ThreadAbortException should be thrown when returning from the transition + PTFF_THREAD_HIJACK = 0x00008000, // indicates that this is a frame for a hijacked call }; #elif defined(TARGET_ARM64) enum PInvokeTransitionFrameFlags : uint64_t @@ -329,13 +328,9 @@ enum PInvokeTransitionFrameFlags : uint64_t // a return address pointing into the hijacked method and that method's // lr register, which may hold a gc pointer - // used by hijack handler to report return value of hijacked method - PTFF_X0_IS_GCREF = 0x0000000100000000, - PTFF_X0_IS_BYREF = 0x0000000200000000, - PTFF_X1_IS_GCREF = 0x0000000400000000, - PTFF_X1_IS_BYREF = 0x0000000800000000, + PTFF_THREAD_ABORT = 0x0000000100000000, // indicates that ThreadAbortException should be thrown when returning from the transition - PTFF_THREAD_ABORT = 0x0000001000000000, // indicates that ThreadAbortException should be thrown when returning from the transition + PTFF_THREAD_HIJACK = 0x0000000200000000, // indicates that this is a frame for a hijacked call }; #elif defined(TARGET_LOONGARCH64) @@ -390,13 +385,9 @@ enum PInvokeTransitionFrameFlags : uint64_t // a return address pointing into the hijacked method and that method's // ra register, which may hold a gc pointer - // used by hijack handler to report return value of hijacked method - PTFF_R4_IS_GCREF = 0x0000000080000000, - PTFF_R4_IS_BYREF = 0x0000000100000000, - PTFF_R5_IS_GCREF = 0x0000000200000000, - PTFF_R5_IS_BYREF = 0x0000000400000000, + PTFF_THREAD_ABORT = 0x0000000080000000, // indicates that ThreadAbortException should be thrown when returning from the transition - PTFF_THREAD_ABORT = 0x0000000800000000, // indicates that ThreadAbortException should be thrown when returning from the transition + PTFF_THREAD_HIJACK = 0x0000000100000000, // indicates that this is a frame for a hijacked call }; #else // TARGET_ARM @@ -434,12 +425,14 @@ enum PInvokeTransitionFrameFlags PTFF_SAVE_R10 = 0x00002000, PTFF_SAVE_R11 = 0x00004000, +#if defined(TARGET_X86) PTFF_RAX_IS_GCREF = 0x00010000, // used by hijack handler to report return value of hijacked method - PTFF_RAX_IS_BYREF = 0x00020000, - PTFF_RDX_IS_GCREF = 0x00040000, - PTFF_RDX_IS_BYREF = 0x00080000, + PTFF_RAX_IS_BYREF = 0x00020000, +#endif PTFF_THREAD_ABORT = 0x00100000, // indicates that ThreadAbortException should be thrown when returning from the transition + + PTFF_THREAD_HIJACK = 0x00200000, // indicates that this is a frame for a hijacked call }; #endif // TARGET_ARM diff --git a/src/coreclr/nativeaot/Runtime/loongarch64/AsmOffsetsCpu.h b/src/coreclr/nativeaot/Runtime/loongarch64/AsmOffsetsCpu.h index cf6c7f5ae690ab..0f48b5f227f8e7 100644 --- a/src/coreclr/nativeaot/Runtime/loongarch64/AsmOffsetsCpu.h +++ b/src/coreclr/nativeaot/Runtime/loongarch64/AsmOffsetsCpu.h @@ -7,7 +7,7 @@ // // NOTE: the offsets MUST be in hex notation WITHOUT the 0x prefix -PLAT_ASM_SIZEOF(280, ExInfo) +PLAT_ASM_SIZEOF(270, ExInfo) PLAT_ASM_OFFSET(0, ExInfo, m_pPrevExInfo) PLAT_ASM_OFFSET(8, ExInfo, m_pExContext) PLAT_ASM_OFFSET(10, ExInfo, m_exception) @@ -15,7 +15,7 @@ PLAT_ASM_OFFSET(18, ExInfo, m_kind) PLAT_ASM_OFFSET(19, ExInfo, m_passNumber) PLAT_ASM_OFFSET(1c, ExInfo, m_idxCurClause) PLAT_ASM_OFFSET(20, ExInfo, m_frameIter) -PLAT_ASM_OFFSET(278, ExInfo, m_notifyDebuggerSP) +PLAT_ASM_OFFSET(268, ExInfo, m_notifyDebuggerSP) PLAT_ASM_OFFSET(0, PInvokeTransitionFrame, m_FramePointer) PLAT_ASM_OFFSET(8, PInvokeTransitionFrame, m_RIP) @@ -23,12 +23,12 @@ PLAT_ASM_OFFSET(10, PInvokeTransitionFrame, m_pThread) PLAT_ASM_OFFSET(18, PInvokeTransitionFrame, m_Flags) PLAT_ASM_OFFSET(20, PInvokeTransitionFrame, m_PreservedRegs) -PLAT_ASM_SIZEOF(258, StackFrameIterator) +PLAT_ASM_SIZEOF(248, StackFrameIterator) PLAT_ASM_OFFSET(10, StackFrameIterator, m_FramePointer) PLAT_ASM_OFFSET(18, StackFrameIterator, m_ControlPC) PLAT_ASM_OFFSET(20, StackFrameIterator, m_RegDisplay) -PLAT_ASM_OFFSET(248, StackFrameIterator, m_OriginalControlPC) -PLAT_ASM_OFFSET(250, StackFrameIterator, m_pPreviousTransitionFrame) +PLAT_ASM_OFFSET(238, StackFrameIterator, m_OriginalControlPC) +PLAT_ASM_OFFSET(240, StackFrameIterator, m_pPreviousTransitionFrame) PLAT_ASM_SIZEOF(B8, PAL_LIMITED_CONTEXT) diff --git a/src/coreclr/nativeaot/Runtime/loongarch64/GcProbe.S b/src/coreclr/nativeaot/Runtime/loongarch64/GcProbe.S index a581021fb56026..d5b7d7f3526496 100644 --- a/src/coreclr/nativeaot/Runtime/loongarch64/GcProbe.S +++ b/src/coreclr/nativeaot/Runtime/loongarch64/GcProbe.S @@ -98,7 +98,6 @@ // // Register state on exit: // a2: thread pointer -// t3: transition frame flags for the return registers a0 and a1 // .macro FixupHijackedCallstack @@ -112,9 +111,8 @@ // // Fix the stack by restoring the original return address // - // Load m_pvHijackedReturnAddress and m_uHijackedReturnValueFlags + // Load m_pvHijackedReturnAddress ld.d $ra, $a2, OFFSETOF__Thread__m_pvHijackedReturnAddress - ld.d $t3, $a2, OFFSETOF__Thread__m_pvHijackedReturnAddress + 8 // // Clear hijack state @@ -122,9 +120,6 @@ // Clear m_ppvHijackedReturnAddressLocation and m_pvHijackedReturnAddress st.d $zero, $a2, OFFSETOF__Thread__m_ppvHijackedReturnAddressLocation st.d $zero, $a2, OFFSETOF__Thread__m_ppvHijackedReturnAddressLocation + 8 - // Clear m_uHijackedReturnValueFlags - st.d $zero, $a2, OFFSETOF__Thread__m_uHijackedReturnValueFlags - .endm // @@ -139,9 +134,8 @@ NESTED_ENTRY RhpGcProbeHijack, _TEXT, NoHandler jirl $r0, $ra, 0 LOCAL_LABEL(WaitForGC): - lu12i.w $t7, ((DEFAULT_FRAME_SAVE_FLAGS + PTFF_SAVE_R4 + PTFF_SAVE_R5) >> 12) & 0xfffff - ori $t7, $t7, (DEFAULT_FRAME_SAVE_FLAGS + PTFF_SAVE_R4 + PTFF_SAVE_R5) & 0xfff - or $t3, $t3, $t7 + lu12i.w $t3, ((DEFAULT_FRAME_SAVE_FLAGS + PTFF_SAVE_R4 + PTFF_SAVE_R5 + PTFF_THREAD_HIJACK) >> 12) & 0xfffff + ori $t3, $t3, (DEFAULT_FRAME_SAVE_FLAGS + PTFF_SAVE_R4 + PTFF_SAVE_R5 + PTFF_THREAD_HIJACK) & 0xfff b C_FUNC(RhpWaitForGC) NESTED_END RhpGcProbeHijack diff --git a/src/coreclr/nativeaot/Runtime/thread.cpp b/src/coreclr/nativeaot/Runtime/thread.cpp index 76beff6c96cf13..aad728782b18be 100644 --- a/src/coreclr/nativeaot/Runtime/thread.cpp +++ b/src/coreclr/nativeaot/Runtime/thread.cpp @@ -451,24 +451,16 @@ void Thread::GcScanRootsWorker(ScanFunc * pfnEnumCallback, ScanContext * pvCallb PTR_OBJECTREF pHijackedReturnValue = NULL; GCRefKind returnValueKind = GCRK_Unknown; +#ifdef TARGET_X86 if (frameIterator.GetHijackedReturnValueLocation(&pHijackedReturnValue, &returnValueKind)) { - GCRefKind reg0Kind = ExtractReg0ReturnKind(returnValueKind); - if (reg0Kind != GCRK_Scalar) - { - EnumGcRef(pHijackedReturnValue, reg0Kind, pfnEnumCallback, pvCallbackData); - } - -#if defined(TARGET_ARM64) || defined(TARGET_UNIX) - GCRefKind reg1Kind = ExtractReg1ReturnKind(returnValueKind); - if (reg1Kind != GCRK_Scalar) + GCRefKind returnKind = ExtractReturnKind(returnValueKind); + if (returnKind != GCRK_Scalar) { - // X0/X1 or RAX/RDX are saved in hijack frame next to each other in this order - EnumGcRef(pHijackedReturnValue + 1, reg1Kind, pfnEnumCallback, pvCallbackData); + EnumGcRef(pHijackedReturnValue, returnKind, pfnEnumCallback, pvCallbackData); } -#endif // TARGET_ARM64 || TARGET_UNIX - } +#endif #ifndef DACCESS_COMPILE if (GetRuntimeInstance()->IsConservativeStackReportingEnabled()) @@ -793,13 +785,11 @@ void Thread::HijackReturnAddress(NATIVE_CONTEXT* pSuspendCtx, HijackFunc* pfnHij void Thread::HijackReturnAddressWorker(StackFrameIterator* frameIterator, HijackFunc* pfnHijackFunction) { void** ppvRetAddrLocation; - GCRefKind retValueKind; frameIterator->CalculateCurrentMethodState(); if (frameIterator->GetCodeManager()->GetReturnAddressHijackInfo(frameIterator->GetMethodInfo(), frameIterator->GetRegisterSet(), - &ppvRetAddrLocation, - &retValueKind)) + &ppvRetAddrLocation)) { ASSERT(ppvRetAddrLocation != NULL); @@ -816,7 +806,12 @@ void Thread::HijackReturnAddressWorker(StackFrameIterator* frameIterator, Hijack m_ppvHijackedReturnAddressLocation = ppvRetAddrLocation; m_pvHijackedReturnAddress = pvRetAddr; - m_uHijackedReturnValueFlags = ReturnKindToTransitionFrameFlags(retValueKind); +#if defined(TARGET_X86) + m_uHijackedReturnValueFlags = ReturnKindToTransitionFrameFlags( + frameIterator->GetCodeManager()->GetReturnValueKind(frameIterator->GetMethodInfo(), + frameIterator->GetRegisterSet())); +#endif + *ppvRetAddrLocation = (void*)pfnHijackFunction; STRESS_LOG2(LF_STACKWALK, LL_INFO10000, "InternalHijack: TgtThread = %llx, IP = %p\n", @@ -950,7 +945,9 @@ void Thread::UnhijackWorker() // Clear the hijack state. m_ppvHijackedReturnAddressLocation = NULL; m_pvHijackedReturnAddress = NULL; +#ifdef TARGET_X86 m_uHijackedReturnValueFlags = 0; +#endif } bool Thread::IsHijacked() @@ -1362,4 +1359,4 @@ EXTERN_C void QCALLTYPE RhSetCurrentThreadName(const TCHAR* name) #else PalSetCurrentThreadName(name); #endif -} \ No newline at end of file +} diff --git a/src/coreclr/nativeaot/Runtime/thread.h b/src/coreclr/nativeaot/Runtime/thread.h index c75ec9a5c4a722..7252e20e84a3ad 100644 --- a/src/coreclr/nativeaot/Runtime/thread.h +++ b/src/coreclr/nativeaot/Runtime/thread.h @@ -142,11 +142,11 @@ struct RuntimeThreadLocals #ifdef FEATURE_HIJACK void ** m_ppvHijackedReturnAddressLocation; void * m_pvHijackedReturnAddress; - uintptr_t m_uHijackedReturnValueFlags; #endif // FEATURE_HIJACK PTR_ExInfo m_pExInfoStackHead; Object* m_threadAbortException; // ThreadAbortException instance -set only during thread abort #ifdef TARGET_X86 + uintptr_t m_uHijackedReturnValueFlags; PCODE m_LastRedirectIP; uint64_t m_SpinCount; #endif diff --git a/src/coreclr/nativeaot/Runtime/unix/UnixNativeCodeManager.cpp b/src/coreclr/nativeaot/Runtime/unix/UnixNativeCodeManager.cpp index 9f982f630bcec7..7f1fdfecc58662 100644 --- a/src/coreclr/nativeaot/Runtime/unix/UnixNativeCodeManager.cpp +++ b/src/coreclr/nativeaot/Runtime/unix/UnixNativeCodeManager.cpp @@ -1168,8 +1168,7 @@ GCRefKind GetGcRefKind(ReturnKind returnKind) bool UnixNativeCodeManager::GetReturnAddressHijackInfo(MethodInfo * pMethodInfo, REGDISPLAY * pRegisterSet, // in - PTR_PTR_VOID * ppvRetAddrLocation, // out - GCRefKind * pRetValueKind) // out + PTR_PTR_VOID * ppvRetAddrLocation) // out { UnixNativeMethodInfo* pNativeMethodInfo = (UnixNativeMethodInfo*)pMethodInfo; @@ -1186,21 +1185,6 @@ bool UnixNativeCodeManager::GetReturnAddressHijackInfo(MethodInfo * pMethodIn if ((unwindBlockFlags & UBF_FUNC_REVERSE_PINVOKE) != 0) return false; - if ((unwindBlockFlags & UBF_FUNC_HAS_ASSOCIATED_DATA) != 0) - p += sizeof(int32_t); - - if ((unwindBlockFlags & UBF_FUNC_HAS_EHINFO) != 0) - p += sizeof(int32_t); - - // Decode the GC info for the current method to determine its return type - GcInfoDecoderFlags flags = DECODE_RETURN_KIND; -#if defined(TARGET_ARM) || defined(TARGET_ARM64) || defined(TARGET_LOONGARCH64) - flags = (GcInfoDecoderFlags)(flags | DECODE_HAS_TAILCALLS); -#endif // TARGET_ARM || TARGET_ARM64 || TARGET_LOONGARCH64 - - GcInfoDecoder decoder(GCInfoToken(p), flags); - *pRetValueKind = GetGcRefKind(decoder.GetReturnKind()); - #if defined(TARGET_ARM) // Ensure that PC doesn't have the Thumb bit set. Prolog and epilog // checks depend on it. @@ -1247,8 +1231,17 @@ bool UnixNativeCodeManager::GetReturnAddressHijackInfo(MethodInfo * pMethodIn *ppvRetAddrLocation = (PTR_PTR_VOID)(pRegisterSet->GetSP() - sizeof(TADDR)); return true; -#elif defined(TARGET_ARM64) || defined(TARGET_ARM) +#elif defined(TARGET_ARM64) || defined(TARGET_ARM) || defined(TARGET_LOONGARCH64) + + if ((unwindBlockFlags & UBF_FUNC_HAS_ASSOCIATED_DATA) != 0) + p += sizeof(int32_t); + + if ((unwindBlockFlags & UBF_FUNC_HAS_EHINFO) != 0) + p += sizeof(int32_t); + // Decode the GC info for the current method to determine if there are tailcalls + GcInfoDecoderFlags flags = DECODE_HAS_TAILCALLS; + GcInfoDecoder decoder(GCInfoToken(p), flags); if (decoder.HasTailCalls()) { // Do not hijack functions that have tail calls, since there are two problems: @@ -1263,6 +1256,7 @@ bool UnixNativeCodeManager::GetReturnAddressHijackInfo(MethodInfo * pMethodIn return false; } +#ifndef TARGET_LOONGARCH64 PTR_uintptr_t pLR = pRegisterSet->pLR; if (!VirtualUnwind(pMethodInfo, pRegisterSet)) { @@ -1280,24 +1274,7 @@ bool UnixNativeCodeManager::GetReturnAddressHijackInfo(MethodInfo * pMethodIn } *ppvRetAddrLocation = (PTR_PTR_VOID)pRegisterSet->pLR; - return true; - -#elif defined(TARGET_LOONGARCH64) - - if (decoder.HasTailCalls()) - { - // Do not hijack functions that have tail calls, since there are two problems: - // 1. When a function that tail calls another one is hijacked, the RA may be - // stored at a different location in the stack frame of the tail call target. - // So just by performing tail call, the hijacked location becomes invalid and - // unhijacking would corrupt stack by writing to that location. - // 2. There is a small window after the caller pops RA from the stack in its - // epilog and before the tail called function pushes RA in its prolog when - // the hijacked return address would not be not on the stack and so we would - // not be able to unhijack. - return false; - } - +#elif PTR_uintptr_t pRA = pRegisterSet->pRA; if (!VirtualUnwind(pMethodInfo, pRegisterSet)) { @@ -1315,6 +1292,8 @@ bool UnixNativeCodeManager::GetReturnAddressHijackInfo(MethodInfo * pMethodIn } *ppvRetAddrLocation = (PTR_PTR_VOID)pRegisterSet->pRA; +#endif // TARGET_LOONGARCH64 + return true; #else return false; diff --git a/src/coreclr/nativeaot/Runtime/unix/UnixNativeCodeManager.h b/src/coreclr/nativeaot/Runtime/unix/UnixNativeCodeManager.h index d7bfe94ac5ff4e..ad9dd8cfed24c1 100644 --- a/src/coreclr/nativeaot/Runtime/unix/UnixNativeCodeManager.h +++ b/src/coreclr/nativeaot/Runtime/unix/UnixNativeCodeManager.h @@ -69,8 +69,7 @@ class UnixNativeCodeManager : public ICodeManager bool GetReturnAddressHijackInfo(MethodInfo * pMethodInfo, REGDISPLAY * pRegisterSet, // in - PTR_PTR_VOID * ppvRetAddrLocation, // out - GCRefKind * pRetValueKind); // out + PTR_PTR_VOID * ppvRetAddrLocation); // out PTR_VOID RemapHardwareFaultToGCSafePoint(MethodInfo * pMethodInfo, PTR_VOID controlPC); diff --git a/src/coreclr/nativeaot/Runtime/unix/unixasmmacrosamd64.inc b/src/coreclr/nativeaot/Runtime/unix/unixasmmacrosamd64.inc index 05667a351a9d8f..e4195ac8ac8311 100644 --- a/src/coreclr/nativeaot/Runtime/unix/unixasmmacrosamd64.inc +++ b/src/coreclr/nativeaot/Runtime/unix/unixasmmacrosamd64.inc @@ -263,6 +263,7 @@ C_FUNC(\Name): #define PTFF_SAVE_RDX 0x00000400 // RDX is saved in hijack handler - in case it contains a GC ref #define PTFF_SAVE_ALL_SCRATCH 0x00007F00 #define PTFF_THREAD_ABORT 0x00100000 // indicates that ThreadAbortException should be thrown when returning from the transition +#define PTFF_THREAD_HIJACK 0x00200000 // indicates that this is a frame for a hijacked call // These must match the TrapThreadsFlags enum #define TrapThreadsFlags_None 0 diff --git a/src/coreclr/nativeaot/Runtime/unix/unixasmmacrosarm.inc b/src/coreclr/nativeaot/Runtime/unix/unixasmmacrosarm.inc index 4ccd38b19c7bef..8aeb084f8e3cd7 100644 --- a/src/coreclr/nativeaot/Runtime/unix/unixasmmacrosarm.inc +++ b/src/coreclr/nativeaot/Runtime/unix/unixasmmacrosarm.inc @@ -18,7 +18,8 @@ #define PTFF_SAVE_R9 0x00000020 #define PTFF_SAVE_SP 0x00000100 #define PTFF_SAVE_R0 0x00000200 -#define PTFF_THREAD_ABORT 0x00100000 +#define PTFF_THREAD_ABORT 0x00004000 +#define PTFF_THREAD_HIJACK 0x00008000 // indicates that this is a frame for a hijacked call #define DEFAULT_FRAME_SAVE_FLAGS (PTFF_SAVE_ALL_PRESERVED + PTFF_SAVE_SP) diff --git a/src/coreclr/nativeaot/Runtime/unix/unixasmmacrosarm64.inc b/src/coreclr/nativeaot/Runtime/unix/unixasmmacrosarm64.inc index a02a770aa3b0af..36698fece5050b 100644 --- a/src/coreclr/nativeaot/Runtime/unix/unixasmmacrosarm64.inc +++ b/src/coreclr/nativeaot/Runtime/unix/unixasmmacrosarm64.inc @@ -306,6 +306,7 @@ C_FUNC(\Name): #define PTFF_SAVE_X0 0x00000800 #define PTFF_SAVE_X1 0x00001000 #define PTFF_SAVE_ALL_PRESERVED 0x000003FF // NOTE: x19-x28 +#define PTFF_THREAD_HIJACK_HI 0x00000002 // upper 32 bits of the PTFF_THREAD_HIJACK #define DEFAULT_FRAME_SAVE_FLAGS (PTFF_SAVE_ALL_PRESERVED + PTFF_SAVE_SP) @@ -345,7 +346,7 @@ C_FUNC(\Name): .endm // Bit position for the flags above, to be used with tbz / tbnz instructions -#define PTFF_THREAD_ABORT_BIT 36 +#define PTFF_THREAD_ABORT_BIT 32 // // CONSTANTS -- INTEGER diff --git a/src/coreclr/nativeaot/Runtime/unix/unixasmmacrosloongarch64.inc b/src/coreclr/nativeaot/Runtime/unix/unixasmmacrosloongarch64.inc index a035a3558cc632..f8b9d1aa633351 100644 --- a/src/coreclr/nativeaot/Runtime/unix/unixasmmacrosloongarch64.inc +++ b/src/coreclr/nativeaot/Runtime/unix/unixasmmacrosloongarch64.inc @@ -309,7 +309,7 @@ C_FUNC(\Name): .endm // Bit position for the flags above, to be used with bstrpick.d+beq/bne instructions -#define PTFF_THREAD_ABORT_BIT 35 +#define PTFF_THREAD_ABORT_BIT 31 // // CONSTANTS -- INTEGER diff --git a/src/coreclr/nativeaot/Runtime/windows/CoffNativeCodeManager.cpp b/src/coreclr/nativeaot/Runtime/windows/CoffNativeCodeManager.cpp index 66c775e0e2c05e..5fe6e446702836 100644 --- a/src/coreclr/nativeaot/Runtime/windows/CoffNativeCodeManager.cpp +++ b/src/coreclr/nativeaot/Runtime/windows/CoffNativeCodeManager.cpp @@ -860,8 +860,7 @@ GCRefKind GetGcRefKind(ReturnKind returnKind) bool CoffNativeCodeManager::GetReturnAddressHijackInfo(MethodInfo * pMethodInfo, REGDISPLAY * pRegisterSet, // in - PTR_PTR_VOID * ppvRetAddrLocation, // out - GCRefKind * pRetValueKind) // out + PTR_PTR_VOID * ppvRetAddrLocation) // out { CoffNativeMethodInfo * pNativeMethodInfo = (CoffNativeMethodInfo *)pMethodInfo; @@ -872,9 +871,6 @@ bool CoffNativeCodeManager::GetReturnAddressHijackInfo(MethodInfo * pMethodIn uint8_t unwindBlockFlags = *p++; - if ((unwindBlockFlags & UBF_FUNC_HAS_ASSOCIATED_DATA) != 0) - p += sizeof(int32_t); - // Check whether this is a funclet if ((unwindBlockFlags & UBF_FUNC_KIND_MASK) != UBF_FUNC_KIND_ROOT) return false; @@ -884,19 +880,7 @@ bool CoffNativeCodeManager::GetReturnAddressHijackInfo(MethodInfo * pMethodIn if ((unwindBlockFlags & UBF_FUNC_REVERSE_PINVOKE) != 0) return false; - if ((unwindBlockFlags & UBF_FUNC_HAS_EHINFO) != 0) - p += sizeof(int32_t); - #ifdef USE_GC_INFO_DECODER - // Decode the GC info for the current method to determine its return type - GcInfoDecoderFlags flags = DECODE_RETURN_KIND; -#if defined(TARGET_ARM64) - flags = (GcInfoDecoderFlags)(flags | DECODE_HAS_TAILCALLS); -#endif // TARGET_ARM64 - GcInfoDecoder decoder(GCInfoToken(p), flags); - - *pRetValueKind = GetGcRefKind(decoder.GetReturnKind()); - // Unwind the current method context to the caller's context to get its stack pointer // and obtain the location of the return address on the stack SIZE_T EstablisherFrame; @@ -924,6 +908,15 @@ bool CoffNativeCodeManager::GetReturnAddressHijackInfo(MethodInfo * pMethodIn return true; #elif defined(TARGET_ARM64) + if ((unwindBlockFlags & UBF_FUNC_HAS_ASSOCIATED_DATA) != 0) + p += sizeof(int32_t); + + if ((unwindBlockFlags & UBF_FUNC_HAS_EHINFO) != 0) + p += sizeof(int32_t); + + // Decode the GC info for the current method to determine if there are tailcalls + GcInfoDecoderFlags flags = DECODE_HAS_TAILCALLS; + GcInfoDecoder decoder(GCInfoToken(p), flags); if (decoder.HasTailCalls()) { // Do not hijack functions that have tail calls, since there are two problems: @@ -1002,12 +995,22 @@ bool CoffNativeCodeManager::GetReturnAddressHijackInfo(MethodInfo * pMethodIn } *ppvRetAddrLocation = (PTR_PTR_VOID)registerSet.PCTAddr; - *pRetValueKind = GetGcRefKind(infoBuf.returnKind); - return true; #endif } +#ifdef TARGET_X86 +GCRefKind CoffNativeCodeManager::GetReturnValueKind(MethodInfo * pMethodInfo, REGDISPLAY * pRegisterSet) +{ + PTR_uint8_t gcInfo; + uint32_t codeOffset = GetCodeOffset(pMethodInfo, (PTR_VOID)pRegisterSet->IP, &gcInfo); + hdrInfo infoBuf; + size_t infoSize = DecodeGCHdrInfo(GCInfoToken(gcInfo), codeOffset, &infoBuf); + + return GetGcRefKind(infoBuf.returnKind); +} +#endif + PTR_VOID CoffNativeCodeManager::RemapHardwareFaultToGCSafePoint(MethodInfo * pMethodInfo, PTR_VOID controlPC) { // GCInfo decoder needs to know whether execution of the method is aborted diff --git a/src/coreclr/nativeaot/Runtime/windows/CoffNativeCodeManager.h b/src/coreclr/nativeaot/Runtime/windows/CoffNativeCodeManager.h index c1dacbfd8f9866..c85f5250967793 100644 --- a/src/coreclr/nativeaot/Runtime/windows/CoffNativeCodeManager.h +++ b/src/coreclr/nativeaot/Runtime/windows/CoffNativeCodeManager.h @@ -91,9 +91,13 @@ class CoffNativeCodeManager : public ICodeManager bool IsUnwindable(PTR_VOID pvAddress); bool GetReturnAddressHijackInfo(MethodInfo * pMethodInfo, - REGDISPLAY * pRegisterSet, // in - PTR_PTR_VOID * ppvRetAddrLocation, // out - GCRefKind * pRetValueKind); // out + REGDISPLAY * pRegisterSet, // in + PTR_PTR_VOID * ppvRetAddrLocation); // out + +#ifdef TARGET_X86 + GCRefKind GetReturnValueKind(MethodInfo * pMethodInfo, + REGDISPLAY * pRegisterSet); +#endif PTR_VOID RemapHardwareFaultToGCSafePoint(MethodInfo * pMethodInfo, PTR_VOID controlPC); diff --git a/src/coreclr/vm/arm/stubs.cpp b/src/coreclr/vm/arm/stubs.cpp index 18ccde9888fb7b..cef0bea5d64793 100644 --- a/src/coreclr/vm/arm/stubs.cpp +++ b/src/coreclr/vm/arm/stubs.cpp @@ -1676,6 +1676,7 @@ void HijackFrame::UpdateRegDisplay(const PREGDISPLAY pRD, bool updateFloats) pRD->pCurrentContext->Sp = PTR_TO_TADDR(m_Args) + sizeof(struct HijackArgs); pRD->pCurrentContext->R0 = m_Args->R0; + pRD->volatileCurrContextPointers.R0 = &m_Args->R0; pRD->pCurrentContext->R4 = m_Args->R4; pRD->pCurrentContext->R5 = m_Args->R5; diff --git a/src/coreclr/vm/arm64/stubs.cpp b/src/coreclr/vm/arm64/stubs.cpp index 6cf5a7ec845896..8f30ba580e39e2 100644 --- a/src/coreclr/vm/arm64/stubs.cpp +++ b/src/coreclr/vm/arm64/stubs.cpp @@ -789,6 +789,10 @@ void HijackFrame::UpdateRegDisplay(const PREGDISPLAY pRD, bool updateFloats) pRD->pCurrentContext->Sp = PTR_TO_TADDR(m_Args) + s ; pRD->pCurrentContext->X0 = m_Args->X0; + pRD->pCurrentContext->X1 = m_Args->X1; + + pRD->volatileCurrContextPointers.X0 = &m_Args->X0; + pRD->volatileCurrContextPointers.X1 = &m_Args->X1; pRD->pCurrentContext->X19 = m_Args->X19; pRD->pCurrentContext->X20 = m_Args->X20; diff --git a/src/coreclr/vm/eetwain.cpp b/src/coreclr/vm/eetwain.cpp index c0655aa471c1c8..25a4c73b65ea0b 100644 --- a/src/coreclr/vm/eetwain.cpp +++ b/src/coreclr/vm/eetwain.cpp @@ -2122,7 +2122,7 @@ size_t EECodeManager::GetFunctionSize(GCInfoToken gcInfoToken) * returns true. * If hijacking is not possible for some reason, it return false. */ -bool EECodeManager::GetReturnAddressHijackInfo(GCInfoToken gcInfoToken, ReturnKind * returnKind) +bool EECodeManager::GetReturnAddressHijackInfo(GCInfoToken gcInfoToken X86_ARG(ReturnKind * returnKind)) { CONTRACTL{ NOTHROW; @@ -2145,7 +2145,7 @@ bool EECodeManager::GetReturnAddressHijackInfo(GCInfoToken gcInfoToken, ReturnKi return true; #else // !USE_GC_INFO_DECODER - GcInfoDecoder gcInfoDecoder(gcInfoToken, GcInfoDecoderFlags(DECODE_RETURN_KIND | DECODE_REVERSE_PINVOKE_VAR)); + GcInfoDecoder gcInfoDecoder(gcInfoToken, GcInfoDecoderFlags(DECODE_REVERSE_PINVOKE_VAR)); if (gcInfoDecoder.GetReversePInvokeFrameStackSlot() != NO_REVERSE_PINVOKE_FRAME) { @@ -2153,7 +2153,6 @@ bool EECodeManager::GetReturnAddressHijackInfo(GCInfoToken gcInfoToken, ReturnKi return false; } - *returnKind = gcInfoDecoder.GetReturnKind(); return true; #endif // USE_GC_INFO_DECODER } diff --git a/src/coreclr/vm/frames.cpp b/src/coreclr/vm/frames.cpp index e6afc8995ef8e1..4b3fd5279303be 100644 --- a/src/coreclr/vm/frames.cpp +++ b/src/coreclr/vm/frames.cpp @@ -1202,7 +1202,7 @@ BOOL IsProtectedByGCFrame(OBJECTREF *ppObjectRef) #endif //!DACCESS_COMPILE #ifdef FEATURE_HIJACK - +#ifdef TARGET_X86 void HijackFrame::GcScanRoots(promote_func *fn, ScanContext* sc) { LIMITED_METHOD_CONTRACT; @@ -1220,9 +1220,7 @@ void HijackFrame::GcScanRoots(promote_func *fn, ScanContext* sc) switch (r) { -#ifdef TARGET_X86 case RT_Float: // Fall through -#endif case RT_Scalar: // nothing to report break; @@ -1248,7 +1246,7 @@ void HijackFrame::GcScanRoots(promote_func *fn, ScanContext* sc) regNo++; } while (moreRegisters); } - +#endif // TARGET_X86 #endif // FEATURE_HIJACK void ProtectByRefsFrame::GcScanRoots(promote_func *fn, ScanContext *sc) diff --git a/src/coreclr/vm/frames.h b/src/coreclr/vm/frames.h index 4ea6e33341d0a3..8fb46b6041fa5a 100644 --- a/src/coreclr/vm/frames.h +++ b/src/coreclr/vm/frames.h @@ -2097,7 +2097,22 @@ class HijackFrame : public Frame } virtual void UpdateRegDisplay(const PREGDISPLAY, bool updateFloats = false); + +#ifdef TARGET_X86 + // On x86 we need to specialcase return values virtual void GcScanRoots(promote_func *fn, ScanContext* sc); +#else + // On non-x86 platforms HijackFrame is just a more compact form of a resumable + // frame with main difference that OnHijackTripThread captures just the registers + // that can possibly contain GC roots. + // The regular reporting of a top frame will report everything that is live + // after the call as specified in GC info, thus we do not need to worry about + // return values. + virtual unsigned GetFrameAttribs() { + LIMITED_METHOD_DAC_CONTRACT; + return FRAME_ATTR_RESUMABLE; // Treat the next frame as the top frame. + } +#endif // HijackFrames are created by trip functions. See OnHijackTripThread() // They are real C++ objects on the stack. diff --git a/src/coreclr/vm/gcinfodecoder.cpp b/src/coreclr/vm/gcinfodecoder.cpp index 40c5c686c6583a..4197e456d8263f 100644 --- a/src/coreclr/vm/gcinfodecoder.cpp +++ b/src/coreclr/vm/gcinfodecoder.cpp @@ -91,9 +91,10 @@ bool GcInfoDecoder::PredecodeFatHeader(int remainingFlags) int numFlagBits = (m_Version == 1) ? GC_INFO_FLAGS_BIT_SIZE_VERSION_1 : GC_INFO_FLAGS_BIT_SIZE; m_headerFlags = (GcInfoHeaderFlags)m_Reader.Read(numFlagBits); - m_ReturnKind = (ReturnKind)((UINT32)m_Reader.Read(SIZE_OF_RETURN_KIND_IN_FAT_HEADER)); + // skip over the unused return kind. + m_Reader.Read(SIZE_OF_RETURN_KIND_IN_FAT_HEADER); - remainingFlags &= ~(DECODE_RETURN_KIND | DECODE_VARARG); + remainingFlags &= ~DECODE_VARARG; #if defined(TARGET_ARM) || defined(TARGET_ARM64) || defined(TARGET_LOONGARCH64) || defined(TARGET_RISCV64) remainingFlags &= ~DECODE_HAS_TAILCALLS; #endif @@ -259,7 +260,6 @@ GcInfoDecoder::GcInfoDecoder( : m_Reader(dac_cast(gcInfoToken.Info)) , m_InstructionOffset(breakOffset) , m_IsInterruptible(false) - , m_ReturnKind(RT_Illegal) #ifdef _DEBUG , m_Flags( flags ) , m_GcInfoAddress(dac_cast(gcInfoToken.Info)) @@ -299,9 +299,10 @@ GcInfoDecoder::GcInfoDecoder( m_StackBaseRegister = NO_STACK_BASE_REGISTER; } - m_ReturnKind = (ReturnKind)((UINT32)m_Reader.Read(SIZE_OF_RETURN_KIND_IN_SLIM_HEADER)); + // skip over the unused return kind. + m_Reader.Read(SIZE_OF_RETURN_KIND_IN_SLIM_HEADER); - remainingFlags &= ~(DECODE_RETURN_KIND | DECODE_VARARG); + remainingFlags &= ~DECODE_VARARG; #if defined(TARGET_ARM) || defined(TARGET_ARM64) || defined(TARGET_LOONGARCH64) || defined(TARGET_RISCV64) remainingFlags &= ~DECODE_HAS_TAILCALLS; #endif @@ -658,13 +659,6 @@ UINT32 GcInfoDecoder::GetCodeLength() return m_CodeLength; } -ReturnKind GcInfoDecoder::GetReturnKind() -{ - // SUPPORTS_DAC; - _ASSERTE( m_Flags & DECODE_RETURN_KIND ); - return m_ReturnKind; -} - UINT32 GcInfoDecoder::GetStackBaseRegister() { return m_StackBaseRegister; diff --git a/src/coreclr/vm/loongarch64/stubs.cpp b/src/coreclr/vm/loongarch64/stubs.cpp index fc047df10fbd45..a73727ee45b783 100644 --- a/src/coreclr/vm/loongarch64/stubs.cpp +++ b/src/coreclr/vm/loongarch64/stubs.cpp @@ -819,6 +819,10 @@ void HijackFrame::UpdateRegDisplay(const PREGDISPLAY pRD, bool updateFloats) pRD->pCurrentContext->Sp = PTR_TO_TADDR(m_Args) + s ; pRD->pCurrentContext->A0 = m_Args->A0; + pRD->pCurrentContext->A1 = m_Args->A1; + + pRD->volatileCurrContextPointers.A0 = &m_Args->A0; + pRD->volatileCurrContextPointers.A1 = &m_Args->A1; pRD->pCurrentContext->S0 = m_Args->S0; pRD->pCurrentContext->S1 = m_Args->S1; diff --git a/src/coreclr/vm/riscv64/stubs.cpp b/src/coreclr/vm/riscv64/stubs.cpp index c170b004388931..026a43c4821906 100644 --- a/src/coreclr/vm/riscv64/stubs.cpp +++ b/src/coreclr/vm/riscv64/stubs.cpp @@ -739,6 +739,11 @@ void HijackFrame::UpdateRegDisplay(const PREGDISPLAY pRD, bool updateFloats) pRD->pCurrentContext->Sp = PTR_TO_TADDR(m_Args) + s ; pRD->pCurrentContext->A0 = m_Args->A0; + pRD->pCurrentContext->A1 = m_Args->A1; + + pRD->volatileCurrContextPointers.A0 = &m_Args->A0; + pRD->volatileCurrContextPointers.A1 = &m_Args->A1; + pRD->pCurrentContext->S1 = m_Args->S1; pRD->pCurrentContext->S2 = m_Args->S2; diff --git a/src/coreclr/vm/threads.cpp b/src/coreclr/vm/threads.cpp index e89b6c7d94c1d0..8951a68905a237 100644 --- a/src/coreclr/vm/threads.cpp +++ b/src/coreclr/vm/threads.cpp @@ -1498,7 +1498,10 @@ Thread::Thread() #ifdef FEATURE_PERFTRACING memset(&m_activityId, 0, sizeof(m_activityId)); #endif // FEATURE_PERFTRACING + +#ifdef TARGET_X86 m_HijackReturnKind = RT_Illegal; +#endif m_currentPrepareCodeConfig = nullptr; m_isInForbidSuspendForDebuggerRegion = false; diff --git a/src/coreclr/vm/threads.h b/src/coreclr/vm/threads.h index 2e125d4ddd78be..40b182b728ef7f 100644 --- a/src/coreclr/vm/threads.h +++ b/src/coreclr/vm/threads.h @@ -2672,7 +2672,7 @@ class Thread private: #ifdef FEATURE_HIJACK - void HijackThread(ReturnKind returnKind, ExecutionState *esb); + void HijackThread(ExecutionState *esb X86_ARG(ReturnKind returnKind)); VOID *m_pvHJRetAddr; // original return address (before hijack) VOID **m_ppvHJRetAddrPtr; // place we bashed a new return address @@ -3843,15 +3843,14 @@ class Thread #endif // FEATURE_PERFTRACING #ifdef FEATURE_HIJACK -private: +#ifdef TARGET_X86 +private: // By the time a frame is scanned by the runtime, m_pHijackReturnKind always // identifies the gc-ness of the return register(s) - ReturnKind m_HijackReturnKind; public: - ReturnKind GetHijackReturnKind() { LIMITED_METHOD_CONTRACT; @@ -3865,6 +3864,7 @@ class Thread m_HijackReturnKind = returnKind; } +#endif #endif // FEATURE_HIJACK public: diff --git a/src/coreclr/vm/threadsuspend.cpp b/src/coreclr/vm/threadsuspend.cpp index 505ceb174684f3..a8e17f902ab0e8 100644 --- a/src/coreclr/vm/threadsuspend.cpp +++ b/src/coreclr/vm/threadsuspend.cpp @@ -4546,7 +4546,7 @@ struct ExecutionState }; // Client is responsible for suspending the thread before calling -void Thread::HijackThread(ReturnKind returnKind, ExecutionState *esb) +void Thread::HijackThread(ExecutionState *esb X86_ARG(ReturnKind returnKind)) { CONTRACTL { NOTHROW; @@ -4554,8 +4554,6 @@ void Thread::HijackThread(ReturnKind returnKind, ExecutionState *esb) } CONTRACTL_END; - _ASSERTE(IsValidReturnKind(returnKind)); - VOID *pvHijackAddr = reinterpret_cast(OnHijackTripThread); #if defined(TARGET_WINDOWS) @@ -4567,10 +4565,13 @@ void Thread::HijackThread(ReturnKind returnKind, ExecutionState *esb) #endif // TARGET_WINDOWS #ifdef TARGET_X86 + _ASSERTE(IsValidReturnKind(returnKind)); if (returnKind == RT_Float) { pvHijackAddr = reinterpret_cast(OnHijackFPTripThread); } + + SetHijackReturnKind(returnKind); #endif // TARGET_X86 // Don't hijack if are in the first level of running a filter/finally/catch. @@ -4590,8 +4591,6 @@ void Thread::HijackThread(ReturnKind returnKind, ExecutionState *esb) return; } - SetHijackReturnKind(returnKind); - if (m_State & TS_Hijacked) UnhijackThread(); @@ -4909,10 +4908,10 @@ void STDCALL OnHijackWorker(HijackArgs * pArgs) #endif // HIJACK_NONINTERRUPTIBLE_THREADS } -static bool GetReturnAddressHijackInfo(EECodeInfo *pCodeInfo, ReturnKind *pReturnKind) +static bool GetReturnAddressHijackInfo(EECodeInfo *pCodeInfo X86_ARG(ReturnKind * returnKind)) { GCInfoToken gcInfoToken = pCodeInfo->GetGCInfoToken(); - return pCodeInfo->GetCodeManager()->GetReturnAddressHijackInfo(gcInfoToken, pReturnKind); + return pCodeInfo->GetCodeManager()->GetReturnAddressHijackInfo(gcInfoToken X86_ARG(returnKind)); } #ifndef TARGET_UNIX @@ -5312,11 +5311,10 @@ BOOL Thread::HandledJITCase() // it or not. EECodeInfo codeInfo(ip); - ReturnKind returnKind; - - if (GetReturnAddressHijackInfo(&codeInfo, &returnKind)) + X86_ONLY(ReturnKind returnKind;) + if (GetReturnAddressHijackInfo(&codeInfo X86_ARG(&returnKind))) { - HijackThread(returnKind, &esb); + HijackThread(&esb X86_ARG(returnKind)); } } } @@ -5852,9 +5850,8 @@ void HandleSuspensionForInterruptedThread(CONTEXT *interruptedContext) if (executionState.m_ppvRetAddrPtr == NULL) return; - ReturnKind returnKind; - - if (!GetReturnAddressHijackInfo(&codeInfo, &returnKind)) + X86_ONLY(ReturnKind returnKind;) + if (!GetReturnAddressHijackInfo(&codeInfo X86_ARG(&returnKind))) { return; } @@ -5868,7 +5865,7 @@ void HandleSuspensionForInterruptedThread(CONTEXT *interruptedContext) StackWalkerWalkingThreadHolder threadStackWalking(pThread); // Hijack the return address to point to the appropriate routine based on the method's return type. - pThread->HijackThread(returnKind, &executionState); + pThread->HijackThread(&executionState X86_ARG(returnKind)); } }