diff --git a/eng/Subsets.props b/eng/Subsets.props index 0f78725c3af98..b769e1c18a0d6 100644 --- a/eng/Subsets.props +++ b/eng/Subsets.props @@ -112,7 +112,7 @@ - true + true true diff --git a/src/coreclr/CMakeLists.txt b/src/coreclr/CMakeLists.txt index ade1e03c92efd..1c314d9bf624e 100644 --- a/src/coreclr/CMakeLists.txt +++ b/src/coreclr/CMakeLists.txt @@ -147,7 +147,7 @@ add_subdirectory(tools/aot/jitinterface) if(NOT CLR_CROSS_COMPONENTS_BUILD) # NativeAOT only buildable for a subset of CoreCLR-supported configurations - if(CLR_CMAKE_HOST_ARCH_ARM64 OR CLR_CMAKE_HOST_ARCH_AMD64) + if(CLR_CMAKE_HOST_ARCH_ARM64 OR CLR_CMAKE_HOST_ARCH_AMD64 OR CLR_CMAKE_HOST_ARCH_ARM) add_subdirectory(nativeaot) endif() endif(NOT CLR_CROSS_COMPONENTS_BUILD) diff --git a/src/coreclr/nativeaot/Runtime/CMakeLists.txt b/src/coreclr/nativeaot/Runtime/CMakeLists.txt index e6d89b44c0c40..b6d871dce5c30 100644 --- a/src/coreclr/nativeaot/Runtime/CMakeLists.txt +++ b/src/coreclr/nativeaot/Runtime/CMakeLists.txt @@ -239,6 +239,9 @@ add_definitions(-DFEATURE_USE_SOFTWARE_WRITE_WATCH_FOR_GC_HEAP) if(CLR_CMAKE_TARGET_ARCH_AMD64 OR CLR_CMAKE_TARGET_ARCH_ARM64) add_definitions(-DFEATURE_MANUALLY_MANAGED_CARD_BUNDLES) endif(CLR_CMAKE_TARGET_ARCH_AMD64 OR CLR_CMAKE_TARGET_ARCH_ARM64) +if(CLR_CMAKE_TARGET_ARCH_ARM) + add_definitions(-DFEATURE_64BIT_ALIGNMENT) +endif(CLR_CMAKE_TARGET_ARCH_ARM) add_definitions(-DFEATURE_CUSTOM_IMPORTS) add_definitions(-DFEATURE_DYNAMIC_CODE) diff --git a/src/coreclr/nativeaot/Runtime/EHHelpers.cpp b/src/coreclr/nativeaot/Runtime/EHHelpers.cpp index f383ff688dad9..957bab172f4f5 100644 --- a/src/coreclr/nativeaot/Runtime/EHHelpers.cpp +++ b/src/coreclr/nativeaot/Runtime/EHHelpers.cpp @@ -27,6 +27,7 @@ #include "rhbinder.h" #include "MethodTable.h" #include "MethodTable.inl" +#include "CommonMacros.inl" COOP_PINVOKE_HELPER(FC_BOOL_RET, RhpEHEnumInitFromStackFrameIterator, ( StackFrameIterator* pFrameIter, void ** pMethodStartAddressOut, EHEnum* pEHEnum)) @@ -327,7 +328,7 @@ static bool InWriteBarrierHelper(uintptr_t faultingIP) ASSERT(*(uint8_t*)writeBarrierAVLocations[i] != 0xE9); // jmp XXXXXXXX #endif - if (writeBarrierAVLocations[i] == faultingIP) + if (PCODEToPINSTR(writeBarrierAVLocations[i]) == faultingIP) return true; } #endif // USE_PORTABLE_HELPERS @@ -368,7 +369,7 @@ static bool InInterfaceDispatchHelper(uintptr_t faultingIP) ASSERT(*(uint8_t*)interfaceDispatchAVLocations[i] != 0xE9); // jmp XXXXXXXX #endif - if (interfaceDispatchAVLocations[i] == faultingIP) + if (PCODEToPINSTR(interfaceDispatchAVLocations[i]) == faultingIP) return true; } #endif // USE_PORTABLE_HELPERS @@ -458,7 +459,7 @@ int32_t __stdcall RhpHardwareExceptionHandler(uintptr_t faultCode, uintptr_t fau { *arg0Reg = faultCode; *arg1Reg = faultingIP; - palContext->SetIp((uintptr_t)&RhpThrowHwEx); + palContext->SetIp(PCODEToPINSTR((PCODE)&RhpThrowHwEx)); return EXCEPTION_CONTINUE_EXECUTION; } @@ -542,7 +543,7 @@ int32_t __stdcall RhpVectoredExceptionHandler(PEXCEPTION_POINTERS pExPtrs) if (translateToManagedException) { - pExPtrs->ContextRecord->SetIp((uintptr_t)&RhpThrowHwEx); + pExPtrs->ContextRecord->SetIp(PCODEToPINSTR((PCODE)&RhpThrowHwEx)); pExPtrs->ContextRecord->SetArg0Reg(faultCode); pExPtrs->ContextRecord->SetArg1Reg(faultingIP); diff --git a/src/coreclr/nativeaot/Runtime/StackFrameIterator.cpp b/src/coreclr/nativeaot/Runtime/StackFrameIterator.cpp index 6e5b0fe1a0c13..1943aa2bcb6d7 100644 --- a/src/coreclr/nativeaot/Runtime/StackFrameIterator.cpp +++ b/src/coreclr/nativeaot/Runtime/StackFrameIterator.cpp @@ -179,8 +179,7 @@ void StackFrameIterator::InternalInit(Thread * pThreadToWalk, PInvokeTransitionF #if !defined(USE_PORTABLE_HELPERS) // @TODO: no portable version of regdisplay memset(&m_RegDisplay, 0, sizeof(m_RegDisplay)); m_RegDisplay.SetIP((PCODE)pFrame->m_RIP); - m_RegDisplay.SetAddrOfIP((PTR_PCODE)PTR_HOST_MEMBER(PInvokeTransitionFrame, pFrame, m_RIP)); - SetControlPC(dac_cast(*(m_RegDisplay.pIP))); + SetControlPC(dac_cast(m_RegDisplay.GetIP())); PTR_UIntNative pPreservedRegsCursor = (PTR_UIntNative)PTR_HOST_MEMBER(PInvokeTransitionFrame, pFrame, m_PreservedRegs); @@ -388,7 +387,6 @@ void StackFrameIterator::InternalInit(Thread * pThreadToWalk, PTR_PAL_LIMITED_CO SetControlPC(dac_cast(pCtx->GetIp())); m_RegDisplay.SP = pCtx->GetSp(); m_RegDisplay.IP = pCtx->GetIp(); - m_RegDisplay.pIP = PTR_TO_MEMBER(PAL_LIMITED_CONTEXT, pCtx, IP); #ifdef TARGET_ARM // @@ -540,8 +538,6 @@ void StackFrameIterator::InternalInit(Thread * pThreadToWalk, NATIVE_CONTEXT* pC #ifdef TARGET_ARM64 - m_RegDisplay.pIP = (PTR_PCODE)PTR_TO_REG(pCtx, Pc); - // // preserved regs // @@ -583,8 +579,6 @@ void StackFrameIterator::InternalInit(Thread * pThreadToWalk, NATIVE_CONTEXT* pC #elif defined(TARGET_X86) || defined(TARGET_AMD64) - m_RegDisplay.pIP = (PTR_PCODE)PTR_TO_REG(pCtx, Rip); - // // preserved regs // @@ -611,6 +605,19 @@ void StackFrameIterator::InternalInit(Thread * pThreadToWalk, NATIVE_CONTEXT* pC m_RegDisplay.pR10 = (PTR_UIntNative)PTR_TO_REG(pCtx, R10); m_RegDisplay.pR11 = (PTR_UIntNative)PTR_TO_REG(pCtx, R11); #endif // TARGET_AMD64 +#elif defined(TARGET_ARM) + + m_RegDisplay.pR0 = (PTR_UIntNative)PTR_TO_REG(pCtx, R0); + m_RegDisplay.pR1 = (PTR_UIntNative)PTR_TO_REG(pCtx, R1); + m_RegDisplay.pR4 = (PTR_UIntNative)PTR_TO_REG(pCtx, R4); + m_RegDisplay.pR5 = (PTR_UIntNative)PTR_TO_REG(pCtx, R5); + m_RegDisplay.pR6 = (PTR_UIntNative)PTR_TO_REG(pCtx, R6); + m_RegDisplay.pR7 = (PTR_UIntNative)PTR_TO_REG(pCtx, R7); + m_RegDisplay.pR8 = (PTR_UIntNative)PTR_TO_REG(pCtx, R8); + m_RegDisplay.pR9 = (PTR_UIntNative)PTR_TO_REG(pCtx, R9); + m_RegDisplay.pR10 = (PTR_UIntNative)PTR_TO_REG(pCtx, R10); + m_RegDisplay.pR11 = (PTR_UIntNative)PTR_TO_REG(pCtx, R11); + m_RegDisplay.pLR = (PTR_UIntNative)PTR_TO_REG(pCtx, Lr); #else PORTABILITY_ASSERT("StackFrameIterator::InternalInit"); #endif // TARGET_ARM @@ -779,10 +786,9 @@ void StackFrameIterator::UnwindFuncletInvokeThunk() #ifdef TARGET_X86 // First, unwind RhpCallFunclet SP = (PTR_UIntNative)(m_RegDisplay.SP + 0x4); // skip the saved assembly-routine-EBP - m_RegDisplay.SetAddrOfIP(SP); m_RegDisplay.SetIP(*SP++); m_RegDisplay.SetSP((uintptr_t)dac_cast(SP)); - SetControlPC(dac_cast(*(m_RegDisplay.pIP))); + SetControlPC(dac_cast(m_RegDisplay.GetIP())); ASSERT( EQUALS_RETURN_ADDRESS(m_ControlPC, RhpCallCatchFunclet2) || @@ -908,12 +914,12 @@ void StackFrameIterator::UnwindFuncletInvokeThunk() SP = (PTR_UIntNative)d; + // RhpCallCatchFunclet puts a couple of extra things on the stack that aren't put there by the other two + // thunks, but we don't need to know what they are here, so we just skip them. + SP += EQUALS_RETURN_ADDRESS(m_ControlPC, RhpCallCatchFunclet2) ? 3 : 1; + if (!isFilterInvoke) { - // RhpCallCatchFunclet puts a couple of extra things on the stack that aren't put there by the other two - // thunks, but we don't need to know what they are here, so we just skip them. - SP += EQUALS_RETURN_ADDRESS(m_ControlPC, RhpCallCatchFunclet2) ? 3 : 1; - // Save the preserved regs portion of the REGDISPLAY across the unwind through the C# EH dispatch code. m_funcletPtrs.pR4 = m_RegDisplay.pR4; m_funcletPtrs.pR5 = m_RegDisplay.pR5; @@ -966,7 +972,6 @@ void StackFrameIterator::UnwindFuncletInvokeThunk() m_RegDisplay.pFP = SP++; - m_RegDisplay.SetAddrOfIP((PTR_PCODE)SP); m_RegDisplay.SetIP(*SP++); m_RegDisplay.pX19 = SP++; @@ -986,12 +991,11 @@ void StackFrameIterator::UnwindFuncletInvokeThunk() #endif #if !defined(TARGET_ARM64) - m_RegDisplay.SetAddrOfIP((PTR_PCODE)SP); m_RegDisplay.SetIP(*SP++); #endif m_RegDisplay.SetSP((uintptr_t)dac_cast(SP)); - SetControlPC(dac_cast(*(m_RegDisplay.pIP))); + SetControlPC(dac_cast(m_RegDisplay.GetIP())); // We expect to be called by the runtime's C# EH implementation, and since this function's notion of how // to unwind through the stub is brittle relative to the stub itself, we want to check as soon as we can. @@ -1170,10 +1174,9 @@ void StackFrameIterator::UnwindUniversalTransitionThunk() stackFrame->UnwindNonVolatileRegisters(&m_RegDisplay); PTR_UIntNative addressOfPushedCallerIP = stackFrame->get_AddressOfPushedCallerIP(); - m_RegDisplay.SetAddrOfIP((PTR_PCODE)addressOfPushedCallerIP); m_RegDisplay.SetIP(*addressOfPushedCallerIP); m_RegDisplay.SetSP((uintptr_t)dac_cast(stackFrame->get_CallerSP())); - SetControlPC(dac_cast(*(m_RegDisplay.pIP))); + SetControlPC(dac_cast(m_RegDisplay.GetIP())); // All universal transition cases rely on conservative GC reporting being applied to the // full argument set that flowed into the call. Report the lower bound of this range (the @@ -1262,7 +1265,6 @@ void StackFrameIterator::UnwindThrowSiteThunk() ASSERT_UNCONDITIONALLY("NYI for this arch"); #endif - m_RegDisplay.SetAddrOfIP(PTR_TO_MEMBER(PAL_LIMITED_CONTEXT, pContext, IP)); m_RegDisplay.SetIP(pContext->IP); m_RegDisplay.SetSP(pContext->GetSp()); SetControlPC(dac_cast(pContext->IP)); @@ -1355,7 +1357,7 @@ void StackFrameIterator::NextInternal() // if the thread is safe to walk, it better not have a hijack in place. ASSERT(!m_pThread->IsHijacked()); - SetControlPC(dac_cast(*(m_RegDisplay.GetAddrOfIP()))); + SetControlPC(dac_cast(m_RegDisplay.GetIP())); PTR_VOID collapsingTargetFrame = NULL; diff --git a/src/coreclr/nativeaot/Runtime/amd64/AsmOffsetsCpu.h b/src/coreclr/nativeaot/Runtime/amd64/AsmOffsetsCpu.h index 8cc7f63f282de..07a73c1e4bcb0 100644 --- a/src/coreclr/nativeaot/Runtime/amd64/AsmOffsetsCpu.h +++ b/src/coreclr/nativeaot/Runtime/amd64/AsmOffsetsCpu.h @@ -71,7 +71,7 @@ PLAT_ASM_OFFSET(90, REGDISPLAY, Xmm) #else // !UNIX_AMD64_ABI -PLAT_ASM_SIZEOF(1b0, ExInfo) +PLAT_ASM_SIZEOF(1a8, ExInfo) PLAT_ASM_OFFSET(0, ExInfo, m_pPrevExInfo) PLAT_ASM_OFFSET(8, ExInfo, m_pExContext) PLAT_ASM_OFFSET(10, ExInfo, m_exception) @@ -79,7 +79,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(1a8, ExInfo, m_notifyDebuggerSP) +PLAT_ASM_OFFSET(1a0, ExInfo, m_notifyDebuggerSP) PLAT_ASM_OFFSET(0, PInvokeTransitionFrame, m_RIP) PLAT_ASM_OFFSET(8, PInvokeTransitionFrame, m_FramePointer) @@ -87,12 +87,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(188, StackFrameIterator) +PLAT_ASM_SIZEOF(180, 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(178, StackFrameIterator, m_OriginalControlPC) -PLAT_ASM_OFFSET(180, StackFrameIterator, m_pPreviousTransitionFrame) +PLAT_ASM_OFFSET(170, StackFrameIterator, m_OriginalControlPC) +PLAT_ASM_OFFSET(178, StackFrameIterator, m_pPreviousTransitionFrame) PLAT_ASM_SIZEOF(50, PAL_LIMITED_CONTEXT) PLAT_ASM_OFFSET(0, PAL_LIMITED_CONTEXT, IP) @@ -108,7 +108,7 @@ PLAT_ASM_OFFSET(38, PAL_LIMITED_CONTEXT, R13) PLAT_ASM_OFFSET(40, PAL_LIMITED_CONTEXT, R14) PLAT_ASM_OFFSET(48, PAL_LIMITED_CONTEXT, R15) -PLAT_ASM_SIZEOF(90, REGDISPLAY) +PLAT_ASM_SIZEOF(88, REGDISPLAY) PLAT_ASM_OFFSET(78, REGDISPLAY, SP) PLAT_ASM_OFFSET(18, REGDISPLAY, pRbx) diff --git a/src/coreclr/nativeaot/Runtime/arm/AsmOffsetsCpu.h b/src/coreclr/nativeaot/Runtime/arm/AsmOffsetsCpu.h index e76a1670de75e..f5b6631f510b2 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(140, ExInfo) +PLAT_ASM_SIZEOF(138, 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(138, ExInfo, m_notifyDebuggerSP) +PLAT_ASM_OFFSET(130, ExInfo, m_notifyDebuggerSP) PLAT_ASM_OFFSET(4, PInvokeTransitionFrame, m_RIP) PLAT_ASM_OFFSET(8, PInvokeTransitionFrame, m_FramePointer) @@ -23,12 +23,12 @@ PLAT_ASM_OFFSET(0c, PInvokeTransitionFrame, m_pThread) PLAT_ASM_OFFSET(10, PInvokeTransitionFrame, m_Flags) PLAT_ASM_OFFSET(14, PInvokeTransitionFrame, m_PreservedRegs) -PLAT_ASM_SIZEOF(120, StackFrameIterator) +PLAT_ASM_SIZEOF(118, 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(114, StackFrameIterator, m_OriginalControlPC) -PLAT_ASM_OFFSET(118, StackFrameIterator, m_pPreviousTransitionFrame) +PLAT_ASM_OFFSET(10c, StackFrameIterator, m_OriginalControlPC) +PLAT_ASM_OFFSET(110, StackFrameIterator, m_pPreviousTransitionFrame) PLAT_ASM_SIZEOF(70, PAL_LIMITED_CONTEXT) PLAT_ASM_OFFSET(24, PAL_LIMITED_CONTEXT, IP) @@ -45,7 +45,7 @@ PLAT_ASM_OFFSET(20, PAL_LIMITED_CONTEXT, R11) PLAT_ASM_OFFSET(28, PAL_LIMITED_CONTEXT, SP) PLAT_ASM_OFFSET(2c, PAL_LIMITED_CONTEXT, LR) -PLAT_ASM_SIZEOF(88, REGDISPLAY) +PLAT_ASM_SIZEOF(80, REGDISPLAY) PLAT_ASM_OFFSET(38, REGDISPLAY, SP) PLAT_ASM_OFFSET(10, REGDISPLAY, pR4) @@ -56,4 +56,4 @@ PLAT_ASM_OFFSET(20, REGDISPLAY, pR8) PLAT_ASM_OFFSET(24, REGDISPLAY, pR9) PLAT_ASM_OFFSET(28, REGDISPLAY, pR10) PLAT_ASM_OFFSET(2c, REGDISPLAY, pR11) -PLAT_ASM_OFFSET(48, REGDISPLAY, D) +PLAT_ASM_OFFSET(40, REGDISPLAY, D) diff --git a/src/coreclr/nativeaot/Runtime/arm/ExceptionHandling.S b/src/coreclr/nativeaot/Runtime/arm/ExceptionHandling.S index 5ba38f1782501..7957793425554 100644 --- a/src/coreclr/nativeaot/Runtime/arm/ExceptionHandling.S +++ b/src/coreclr/nativeaot/Runtime/arm/ExceptionHandling.S @@ -62,6 +62,10 @@ NESTED_ENTRY RhpThrowHwEx, _TEXT, NoHandler str r3, [r1, #OFFSETOF__ExInfo__m_pPrevExInfo] // pExInfo->m_pPrevExInfo = m_pExInfoStackHead str r1, [r0, #OFFSETOF__Thread__m_pExInfoStackHead] // m_pExInfoStackHead = pExInfo + // set the exception context field on the ExInfo + add r2, sp, #rsp_offsetof_Context // r2 <- PAL_LIMITED_CONTEXT* + str r2, [r1, #OFFSETOF__ExInfo__m_pExContext] // pExInfo->m_pExContext = pContext + mov r0, r4 // restore the exception code // r0 contains the exception code // r1 contains the address of the ExInfo diff --git a/src/coreclr/nativeaot/Runtime/arm/GcProbe.S b/src/coreclr/nativeaot/Runtime/arm/GcProbe.S index 87ead1311f3c7..52fee44368288 100644 --- a/src/coreclr/nativeaot/Runtime/arm/GcProbe.S +++ b/src/coreclr/nativeaot/Runtime/arm/GcProbe.S @@ -1,14 +1,16 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +.syntax unified +.thumb + #include #include "AsmOffsets.inc" .global RhpGcPoll2 LEAF_ENTRY RhpGcPoll - ldr r0, =RhpTrapThreads - ldr r0, [r0] + PREPARE_EXTERNAL_VAR_INDIRECT RhpTrapThreads, r0 cmp r0, #TrapThreadsFlags_None bne RhpGcPollRare bx lr diff --git a/src/coreclr/nativeaot/Runtime/arm/InteropThunksHelpers.S b/src/coreclr/nativeaot/Runtime/arm/InteropThunksHelpers.S index d8012f088a6ec..eec5523d67500 100644 --- a/src/coreclr/nativeaot/Runtime/arm/InteropThunksHelpers.S +++ b/src/coreclr/nativeaot/Runtime/arm/InteropThunksHelpers.S @@ -42,7 +42,7 @@ NESTED_END RhCommonStub, _TEXT // IntPtr RhGetCommonStubAddress() // LEAF_ENTRY RhGetCommonStubAddress, _TEXT - ldr r0, =C_FUNC(RhCommonStub) + PREPARE_EXTERNAL_VAR RhCommonStub, r0 bx lr LEAF_END RhGetCommonStubAddress, _TEXT diff --git a/src/coreclr/nativeaot/Runtime/arm/PInvoke.S b/src/coreclr/nativeaot/Runtime/arm/PInvoke.S index eda3ccdc66195..39136c17935ea 100644 --- a/src/coreclr/nativeaot/Runtime/arm/PInvoke.S +++ b/src/coreclr/nativeaot/Runtime/arm/PInvoke.S @@ -49,8 +49,7 @@ LEAF_ENTRY RhpPInvokeReturn, _TEXT mov r2, #0 str r2, [r3, #OFFSETOF__Thread__m_pTransitionFrame] - ldr r3, =C_FUNC(RhpTrapThreads) - ldr r3, [r3] + PREPARE_EXTERNAL_VAR_INDIRECT RhpTrapThreads, r3 cbnz r3, LOCAL_LABEL(ReturnRareTrapThread) // TrapThreadsFlags_None = 0 bx lr diff --git a/src/coreclr/nativeaot/Runtime/arm/StubDispatch.S b/src/coreclr/nativeaot/Runtime/arm/StubDispatch.S index 331b6bd27d8e9..05cf4f919817d 100644 --- a/src/coreclr/nativeaot/Runtime/arm/StubDispatch.S +++ b/src/coreclr/nativeaot/Runtime/arm/StubDispatch.S @@ -125,7 +125,7 @@ LEAF_ENTRY RhpInterfaceDispatchSlow, _TEXT // for the universal thunk target is to be placed in sp-8 // and the universal thunk target address is to be placed in sp-4 str r12, [sp, #-8] - ldr r12, =C_FUNC(RhpCidResolve) + PREPARE_EXTERNAL_VAR RhpCidResolve, r12 str r12, [sp, #-4] // jump to universal transition thunk diff --git a/src/coreclr/nativeaot/Runtime/arm/UniversalTransition.S b/src/coreclr/nativeaot/Runtime/arm/UniversalTransition.S index 46a3929b9301a..5db9aa8847d08 100644 --- a/src/coreclr/nativeaot/Runtime/arm/UniversalTransition.S +++ b/src/coreclr/nativeaot/Runtime/arm/UniversalTransition.S @@ -102,7 +102,7 @@ NESTED_ENTRY Rhp\FunctionName, _TEXT, NoHandler // frame, and the code at the call target is required to use only the transition frame // copies when dispatching this call to the eventual callee. - ldr r3, =C_FUNC(RhpFpTrashValues) + PREPARE_EXTERNAL_VAR RhpFpTrashValues, r3 vldr d0, [r3, #(0 * 8)] vldr d1, [r3, #(1 * 8)] vldr d2, [r3, #(2 * 8)] @@ -112,7 +112,7 @@ NESTED_ENTRY Rhp\FunctionName, _TEXT, NoHandler vldr d6, [r3, #(6 * 8)] vldr d7, [r3, #(7 * 8)] - ldr r3, =C_FUNC(RhpIntegerTrashValues) + PREPARE_EXTERNAL_VAR RhpIntegerTrashValues, r3 ldr r2, [r3, #(2 * 4)] ldr r3, [r3, #(3 * 4)] diff --git a/src/coreclr/nativeaot/Runtime/arm/WriteBarriers.S b/src/coreclr/nativeaot/Runtime/arm/WriteBarriers.S index 30e20c4bea401..2d22c9bf1f18b 100644 --- a/src/coreclr/nativeaot/Runtime/arm/WriteBarriers.S +++ b/src/coreclr/nativeaot/Runtime/arm/WriteBarriers.S @@ -12,8 +12,7 @@ .macro UPDATE_GC_SHADOW BASENAME, REFREG, DESTREG // If g_GCShadow is 0, don't perform the check. - ldr r12, =C_FUNC(g_GCShadow) - ldr r12, [r12] + PREPARE_EXTERNAL_VAR_INDIRECT g_GCShadow, r12 cbz r12, LOCAL_LABEL(\BASENAME\()_UpdateShadowHeap_Done_\REFREG) // Save DESTREG since we're about to modify it (and we need the original value both within the macro and @@ -27,16 +26,13 @@ push \DESTREG // Transform DESTREG into the equivalent address in the shadow heap. - ldr r12, =C_FUNC(g_lowest_address) - ldr r12, [r12] + PREPARE_EXTERNAL_VAR_INDIRECT g_lowest_address, r12 sub \DESTREG, r12 cmp \DESTREG, #0 blo LOCAL_LABEL(\BASENAME\()_UpdateShadowHeap_PopThenDone_\REFREG) - ldr r12, =C_FUNC(g_GCShadow) - ldr r12, [r12] + PREPARE_EXTERNAL_VAR_INDIRECT g_GCShadow, r12 add \DESTREG, r12 - ldr r12, =C_FUNC(g_GCShadowEnd) - ldr r12, [r12] + PREPARE_EXTERNAL_VAR_INDIRECT g_GCShadowEnd, r12 cmp \DESTREG, r12 bhs LOCAL_LABEL(\BASENAME\()_UpdateShadowHeap_PopThenDone_\REFREG) @@ -105,13 +101,11 @@ LOCAL_LABEL(\BASENAME\()_UpdateShadowHeap_Done_\REFREG): // If the reference is to an object that's not in an ephemeral generation we have no need to track it // (since the object won't be collected or moved by an ephemeral collection). - ldr r12, =C_FUNC(g_ephemeral_low) - ldr r12, [r12] + PREPARE_EXTERNAL_VAR_INDIRECT g_ephemeral_low, r12 cmp \REFREG, r12 blo LOCAL_LABEL(\BASENAME\()_EXIT_\REFREG) - ldr r12, =C_FUNC(g_ephemeral_high) - ldr r12, [r12] + PREPARE_EXTERNAL_VAR_INDIRECT g_ephemeral_high, r12 cmp \REFREG, r12 bhs LOCAL_LABEL(\BASENAME\()_EXIT_\REFREG) @@ -119,8 +113,7 @@ LOCAL_LABEL(\BASENAME\()_UpdateShadowHeap_Done_\REFREG): // track this write. The location address is translated into an offset in the card table bitmap. We set // an entire byte in the card table since it's quicker than messing around with bitmasks and we only write // the byte if it hasn't already been done since writes are expensive and impact scaling. - ldr r12, =C_FUNC(g_card_table) - ldr r12, [r12] + PREPARE_EXTERNAL_VAR_INDIRECT g_card_table, r12 add r0, r12, r0, lsr #LOG2_CLUMP_SIZE ldrb r12, [r0] cmp r12, #0x0FF @@ -198,12 +191,10 @@ DEFINE_UNCHECKED_WRITE_BARRIER r1, r1 // The location being updated might not even lie in the GC heap (a handle or stack location for instance), // in which case no write barrier is required. - ldr r12, =C_FUNC(g_lowest_address) - ldr r12, [r12] + PREPARE_EXTERNAL_VAR_INDIRECT g_lowest_address, r12 cmp r0, r12 blo LOCAL_LABEL(\BASENAME\()_NoBarrierRequired_\REFREG) - ldr r12, =C_FUNC(g_highest_address) - ldr r12, [r12] + PREPARE_EXTERNAL_VAR_INDIRECT g_highest_address, r12 cmp r0, r12 bhs LOCAL_LABEL(\BASENAME\()_NoBarrierRequired_\REFREG) @@ -335,12 +326,10 @@ ALTERNATE_ENTRY RhpByRefAssignRefAVLocation2 str r2, [r0] // Check whether the writes were even into the heap. If not there's no card update required. - ldr r3, =C_FUNC(g_lowest_address) - ldr r3, [r3] + PREPARE_EXTERNAL_VAR_INDIRECT g_lowest_address, r3 cmp r0, r3 blo LOCAL_LABEL(RhpByRefAssignRef_NotInHeap) - ldr r3, =C_FUNC(g_highest_address) - ldr r3, [r3] + PREPARE_EXTERNAL_VAR_INDIRECT g_highest_address, r3 cmp r0, r3 bhs LOCAL_LABEL(RhpByRefAssignRef_NotInHeap) @@ -350,12 +339,10 @@ ALTERNATE_ENTRY RhpByRefAssignRefAVLocation2 // If the reference is to an object that's not in an ephemeral generation we have no need to track it // (since the object won't be collected or moved by an ephemeral collection). - ldr r3, =C_FUNC(g_ephemeral_low) - ldr r3, [r3] + PREPARE_EXTERNAL_VAR_INDIRECT g_ephemeral_low, r3 cmp r2, r3 blo LOCAL_LABEL(RhpByRefAssignRef_NotInHeap) - ldr r3, =C_FUNC(g_ephemeral_high) - ldr r3, [r3] + PREPARE_EXTERNAL_VAR_INDIRECT g_ephemeral_high, r3 cmp r2, r3 bhs LOCAL_LABEL(RhpByRefAssignRef_NotInHeap) @@ -368,8 +355,7 @@ ALTERNATE_ENTRY RhpByRefAssignRefAVLocation2 // track this write. The location address is translated into an offset in the card table bitmap. We set // an entire byte in the card table since it's quicker than messing around with bitmasks and we only write // the byte if it hasn't already been done since writes are expensive and impact scaling. - ldr r3, =C_FUNC(g_card_table) - ldr r3, [r3] + PREPARE_EXTERNAL_VAR_INDIRECT g_card_table, r3 add r2, r3, r2, lsr #LOG2_CLUMP_SIZE ldrb r3, [r2] cmp r3, #0x0FF diff --git a/src/coreclr/nativeaot/Runtime/arm64/AsmOffsetsCpu.h b/src/coreclr/nativeaot/Runtime/arm64/AsmOffsetsCpu.h index cfef3d7f05f08..529ab2c47331f 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(298, ExInfo) +PLAT_ASM_SIZEOF(290, 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(290, ExInfo, m_notifyDebuggerSP) +PLAT_ASM_OFFSET(288, 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(270, StackFrameIterator) +PLAT_ASM_SIZEOF(268, 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(260, StackFrameIterator, m_OriginalControlPC) -PLAT_ASM_OFFSET(268, StackFrameIterator, m_pPreviousTransitionFrame) +PLAT_ASM_OFFSET(258, StackFrameIterator, m_OriginalControlPC) +PLAT_ASM_OFFSET(260, StackFrameIterator, m_pPreviousTransitionFrame) PLAT_ASM_SIZEOF(C0, PAL_LIMITED_CONTEXT) @@ -49,7 +49,7 @@ PLAT_ASM_OFFSET(68, PAL_LIMITED_CONTEXT, X28) PLAT_ASM_OFFSET(70, PAL_LIMITED_CONTEXT, SP) PLAT_ASM_OFFSET(78, PAL_LIMITED_CONTEXT, IP) -PLAT_ASM_SIZEOF(150, REGDISPLAY) +PLAT_ASM_SIZEOF(148, REGDISPLAY) PLAT_ASM_OFFSET(f8, REGDISPLAY, SP) PLAT_ASM_OFFSET(98, REGDISPLAY, pX19) @@ -64,4 +64,4 @@ PLAT_ASM_OFFSET(d8, REGDISPLAY, pX27) PLAT_ASM_OFFSET(e0, REGDISPLAY, pX28) PLAT_ASM_OFFSET(e8, REGDISPLAY, pFP) PLAT_ASM_OFFSET(f0, REGDISPLAY, pLR) -PLAT_ASM_OFFSET(110, REGDISPLAY, D) +PLAT_ASM_OFFSET(108, REGDISPLAY, D) diff --git a/src/coreclr/nativeaot/Runtime/regdisplay.h b/src/coreclr/nativeaot/Runtime/regdisplay.h index eae75eabe2e6c..0246d0039477a 100644 --- a/src/coreclr/nativeaot/Runtime/regdisplay.h +++ b/src/coreclr/nativeaot/Runtime/regdisplay.h @@ -30,7 +30,6 @@ struct REGDISPLAY #endif // TARGET_AMD64 uintptr_t SP; - PTR_PCODE pIP; PCODE IP; #if defined(TARGET_AMD64) && !defined(UNIX_AMD64_ABI) @@ -41,13 +40,11 @@ struct REGDISPLAY #endif // TARGET_AMD64 && !UNIX_AMD64_ABI inline PCODE GetIP() { return IP; } - inline PTR_PCODE GetAddrOfIP() { return pIP; } inline uintptr_t GetSP() { return SP; } inline uintptr_t GetFP() { return *pRbp; } inline uintptr_t GetPP() { return *pRbx; } inline void SetIP(PCODE IP) { this->IP = IP; } - inline void SetAddrOfIP(PTR_PCODE pIP) { this->pIP = pIP; } inline void SetSP(uintptr_t SP) { this->SP = SP; } }; @@ -71,7 +68,6 @@ struct REGDISPLAY PTR_UIntNative pLR; uintptr_t SP; - PTR_PCODE pIP; PCODE IP; uint64_t D[16-8]; // preserved D registers D8..D15 (note that D16-D31 are not preserved according to the ABI spec) @@ -80,11 +76,9 @@ struct REGDISPLAY // their values, not their addresses inline PCODE GetIP() { return IP; } - inline PTR_PCODE GetAddrOfIP() { return pIP; } inline uintptr_t GetSP() { return SP; } inline uintptr_t GetFP() { return *pR11; } inline void SetIP(PCODE IP) { this->IP = IP; } - inline void SetAddrOfIP(PTR_PCODE pIP) { this->pIP = pIP; } inline void SetSP(uintptr_t SP) { this->SP = SP; } }; @@ -125,7 +119,6 @@ struct REGDISPLAY PTR_UIntNative pLR; // X30 uintptr_t SP; - PTR_PCODE pIP; PCODE IP; uint64_t D[16-8]; // Only the bottom 64-bit value of the V registers V8..V15 needs to be preserved @@ -135,12 +128,10 @@ struct REGDISPLAY // their values, not their addresses inline PCODE GetIP() { return IP; } - inline PTR_PCODE GetAddrOfIP() { return pIP; } inline uintptr_t GetSP() { return SP; } inline uintptr_t GetFP() { return *pFP; } inline void SetIP(PCODE IP) { this->IP = IP; } - inline void SetAddrOfIP(PTR_PCODE pIP) { this->pIP = pIP; } inline void SetSP(uintptr_t SP) { this->SP = SP; } }; #elif defined(TARGET_WASM) @@ -150,16 +141,13 @@ struct REGDISPLAY // TODO: WebAssembly doesn't really have registers. What exactly do we need here? uintptr_t SP; - PTR_PCODE pIP; PCODE IP; inline PCODE GetIP() { return NULL; } - inline PTR_PCODE GetAddrOfIP() { return NULL; } inline uintptr_t GetSP() { return 0; } inline uintptr_t GetFP() { return 0; } inline void SetIP(PCODE IP) { } - inline void SetAddrOfIP(PTR_PCODE pIP) { } inline void SetSP(uintptr_t SP) { } }; #endif // HOST_X86 || HOST_AMD64 || HOST_ARM || HOST_ARM64 || HOST_WASM diff --git a/src/coreclr/nativeaot/Runtime/unix/UnixNativeCodeManager.cpp b/src/coreclr/nativeaot/Runtime/unix/UnixNativeCodeManager.cpp index 9407499e329ca..2a75e83bbfdfb 100644 --- a/src/coreclr/nativeaot/Runtime/unix/UnixNativeCodeManager.cpp +++ b/src/coreclr/nativeaot/Runtime/unix/UnixNativeCodeManager.cpp @@ -87,12 +87,12 @@ bool UnixNativeCodeManager::FindMethodInfo(PTR_VOID ControlPC, unw_proc_info_t procInfo; - if (!UnwindHelpers::GetUnwindProcInfo((PCODE)ControlPC, m_UnwindInfoSections, &procInfo)) + if (!UnwindHelpers::GetUnwindProcInfo(PINSTRToPCODE((TADDR)ControlPC), m_UnwindInfoSections, &procInfo)) { return false; } - assert((procInfo.start_ip <= (PCODE)ControlPC) && ((PCODE)ControlPC < procInfo.end_ip)); + assert((procInfo.start_ip <= PINSTRToPCODE((TADDR)ControlPC)) && (PINSTRToPCODE((TADDR)ControlPC) < procInfo.end_ip)); pMethodInfo->start_ip = procInfo.start_ip; pMethodInfo->format = procInfo.format; @@ -607,7 +607,7 @@ int UnixNativeCodeManager::TrailingEpilogueInstructionsCount(MethodInfo * pMetho { unw_proc_info_t procInfo; - bool result = UnwindHelpers::GetUnwindProcInfo((PCODE)pvAddress, m_UnwindInfoSections, &procInfo); + bool result = UnwindHelpers::GetUnwindProcInfo(PINSTRToPCODE((TADDR)pvAddress), m_UnwindInfoSections, &procInfo); ASSERT(result); if (branchTarget < procInfo.start_ip || branchTarget >= procInfo.end_ip) diff --git a/src/coreclr/nativeaot/Runtime/unix/UnwindHelpers.cpp b/src/coreclr/nativeaot/Runtime/unix/UnwindHelpers.cpp index 6fd0df0c63546..91ccc1e631d96 100644 --- a/src/coreclr/nativeaot/Runtime/unix/UnwindHelpers.cpp +++ b/src/coreclr/nativeaot/Runtime/unix/UnwindHelpers.cpp @@ -109,7 +109,6 @@ struct Registers_REGDISPLAY : REGDISPLAY case UNW_REG_IP: case UNW_X86_64_RIP: IP = value; - pIP = (PTR_PCODE)location; return; case UNW_REG_SP: SP = value; @@ -198,11 +197,7 @@ struct Registers_REGDISPLAY : REGDISPLAY uint64_t getIP() const { return IP; } - void setIP(uint64_t value, uint64_t location) - { - IP = value; - pIP = (PTR_PCODE)location; - } + void setIP(uint64_t value, uint64_t location) { IP = value; } uint64_t getRBP() const { return *pRbp; } void setRBP(uint64_t value, uint64_t location) { pRbp = (PTR_UIntNative)location; } @@ -260,7 +255,6 @@ struct Registers_REGDISPLAY : REGDISPLAY { case UNW_REG_IP: IP = value; - pIP = (PTR_PCODE)location; return; case UNW_REG_SP: SP = value; @@ -324,11 +318,7 @@ struct Registers_REGDISPLAY : REGDISPLAY uint64_t getIP() const { return IP; } - void setIP(uint64_t value, uint64_t location) - { - IP = value; - pIP = (PTR_PCODE)location; - } + void setIP(uint64_t value, uint64_t location) { IP = value; } uint64_t getEBP() const { return *pRbp; } void setEBP(uint64_t value, uint64_t location) { pRbp = (PTR_UIntNative)location; } @@ -360,8 +350,7 @@ struct Registers_REGDISPLAY : REGDISPLAY uint32_t getSP() const { return SP;} void setSP(uint32_t value, uint32_t location) { SP = value;} uint32_t getIP() const { return IP;} - void setIP(uint32_t value, uint32_t location) - { IP = value; pIP = (PTR_UIntNative)location; } + void setIP(uint32_t value, uint32_t location) { IP = value; } uint32_t getFP() const { return *pR11;} void setFP(uint32_t value, uint32_t location) { pR11 = (PTR_UIntNative)location;} }; @@ -439,12 +428,6 @@ void Registers_REGDISPLAY::setRegister(int num, uint32_t value, uint32_t locatio if (num == UNW_REG_IP || num == UNW_ARM_IP) { IP = value; - /* the location could be NULL, we could try to recover - pointer to value in stack from pLR */ - if ((!location) && pLR && (*pLR == value)) - pIP = pLR; - else - pIP = (PTR_UIntNative)location; return; } @@ -520,8 +503,7 @@ struct Registers_REGDISPLAY : REGDISPLAY uint64_t getSP() const { return SP;} void setSP(uint64_t value, uint64_t location) { SP = value;} uint64_t getIP() const { return IP;} - void setIP(uint64_t value, uint64_t location) - { IP = value; pIP = (PTR_UIntNative)location; } + void setIP(uint64_t value, uint64_t location) { IP = value; } uint64_t getFP() const { return *pFP;} void setFP(uint64_t value, uint64_t location) { pFP = (PTR_UIntNative)location;} }; @@ -815,10 +797,6 @@ bool UnwindHelpers::StepFrame(REGDISPLAY *regs, unw_word_t start_ip, uint32_t fo return false; } -#if !defined(TARGET_ARM64) - regs->pIP = PTR_PCODE(regs->SP - sizeof(TADDR)); -#endif - #elif defined(_LIBUNWIND_ARM_EHABI) PORTABILITY_ASSERT("StepFrame"); #else diff --git a/src/coreclr/nativeaot/Runtime/unix/unixasmmacrosarm.inc b/src/coreclr/nativeaot/Runtime/unix/unixasmmacrosarm.inc index 9f1d17a46188a..7961fdb1dbcf4 100644 --- a/src/coreclr/nativeaot/Runtime/unix/unixasmmacrosarm.inc +++ b/src/coreclr/nativeaot/Runtime/unix/unixasmmacrosarm.inc @@ -68,7 +68,16 @@ C_FUNC(\Name): .endm .macro PREPARE_EXTERNAL_VAR Name, HelperReg - ldr \HelperReg, [pc, #C_FUNC(\Name)@GOTPCREL] + movw \HelperReg, #:lower16:C_FUNC(\Name) - (. + 12) + movt \HelperReg, #:upper16:C_FUNC(\Name) - (. + 12) + add \HelperReg, pc +.endm + +.macro PREPARE_EXTERNAL_VAR_INDIRECT Name, HelperReg + movw \HelperReg, #:lower16:C_FUNC(\Name) - (. + 12) + movt \HelperReg, #:upper16:C_FUNC(\Name) - (. + 12) + add \HelperReg, pc + ldr \HelperReg, [\HelperReg] .endm .macro push_nonvol_reg Register diff --git a/src/coreclr/nativeaot/Runtime/windows/CoffNativeCodeManager.cpp b/src/coreclr/nativeaot/Runtime/windows/CoffNativeCodeManager.cpp index cc409cf2167a1..cbdec015f117c 100644 --- a/src/coreclr/nativeaot/Runtime/windows/CoffNativeCodeManager.cpp +++ b/src/coreclr/nativeaot/Runtime/windows/CoffNativeCodeManager.cpp @@ -636,8 +636,6 @@ bool CoffNativeCodeManager::UnwindStackFrame(MethodInfo * pMethodInfo, pRegisterSet->SP = context.Rsp; pRegisterSet->IP = context.Rip; - pRegisterSet->pIP = PTR_PCODE(pRegisterSet->SP - sizeof(TADDR)); - if (!(flags & USFF_GcUnwind)) { memcpy(pRegisterSet->Xmm, &context.Xmm6, sizeof(pRegisterSet->Xmm)); @@ -667,8 +665,6 @@ bool CoffNativeCodeManager::UnwindStackFrame(MethodInfo * pMethodInfo, pRegisterSet->SP = context.Sp; pRegisterSet->IP = context.Pc; - pRegisterSet->pIP = contextPointers.Lr; - if (!(flags & USFF_GcUnwind)) { for (int i = 8; i < 16; i++) diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/ObjectWriter/ElfObjectWriter.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/ObjectWriter/ElfObjectWriter.cs index 17fa66b7c7a3f..aa4b39552b693 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/ObjectWriter/ElfObjectWriter.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/ObjectWriter/ElfObjectWriter.cs @@ -169,18 +169,13 @@ protected internal override unsafe void EmitRelocation( { fixed (byte *pData = data) { - if (relocType is IMAGE_REL_BASED_REL32 && _machine is EM_386 or EM_X86_64) + addend -= relocType switch { - addend -= 4; - } - else if (relocType is IMAGE_REL_BASED_THUMB_BRANCH24) - { - addend -= 4; - } - else if (relocType is IMAGE_REL_BASED_THUMB_MOV32_PCREL) - { - addend -= 12; - } + IMAGE_REL_BASED_REL32 => 4, + IMAGE_REL_BASED_THUMB_BRANCH24 => 4, + IMAGE_REL_BASED_THUMB_MOV32_PCREL => 12, + _ => 0 + }; if (!_useInlineRelocationAddends) { @@ -196,12 +191,24 @@ protected internal override unsafe void EmitRelocation( } else { - if (addend != 0) + if (relocType is IMAGE_REL_BASED_THUMB_MOV32_PCREL or IMAGE_REL_BASED_THUMB_MOV32) + { + long inlineValue = Relocation.ReadValue(relocType, (void*)pData); + addend += inlineValue; + Debug.Assert(addend >= short.MinValue && addend <= short.MaxValue); + // This expands into two relocations where each of them has to have the + // same base 16-bit addend + PC difference between the two instructions. + addend = relocType is IMAGE_REL_BASED_THUMB_MOV32_PCREL ? + (long)((((uint)(addend + 4) & 0xffff) << 16) + (ushort)addend) : + (long)((((uint)(addend) & 0xffff) << 16) + (ushort)addend); + Relocation.WriteValue(relocType, (void*)pData, addend); + } + else if (addend != 0) { long inlineValue = Relocation.ReadValue(relocType, (void*)pData); Relocation.WriteValue(relocType, (void*)pData, inlineValue + addend); - addend = 0; } + addend = 0; } } @@ -219,11 +226,10 @@ private protected override void EmitSymbolTable( var type = (section.SectionHeader.Flags & SHF_TLS) == SHF_TLS ? STT_TLS : definition.Size > 0 ? STT_FUNC : STT_NOTYPE; - ulong thumbBit = _machine == EM_ARM && type == STT_FUNC ? 1u : 0u; sortedSymbols.Add(new ElfSymbol { Name = name, - Value = (ulong)definition.Value | thumbBit, + Value = (ulong)definition.Value, Size = (ulong)definition.Size, Section = _sections[definition.SectionIndex], Info = (byte)(type | (STB_GLOBAL << 4)), diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/ObjectWriter/ObjectWriter.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/ObjectWriter/ObjectWriter.cs index fde0bb8a53d01..042cf91bc238c 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/ObjectWriter/ObjectWriter.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/ObjectWriter/ObjectWriter.cs @@ -12,6 +12,7 @@ using Internal.TypeSystem; using Internal.TypeSystem.TypesDebugInfo; using ObjectData = ILCompiler.DependencyAnalysis.ObjectNode.ObjectData; +using static ILCompiler.DependencyAnalysis.RelocType; namespace ILCompiler.ObjectWriter { @@ -144,7 +145,7 @@ private protected static ObjectNodeSection GetSharedSection(ObjectNodeSection se return new ObjectNodeSection(standardSectionPrefix + section.Name, section.Type, key); } - private void EmitOrResolveRelocation( + private unsafe void EmitOrResolveRelocation( int sectionIndex, long offset, Span data, @@ -153,32 +154,41 @@ private void EmitOrResolveRelocation( long addend) { if (!_usesSubsectionsViaSymbols && - relocType is RelocType.IMAGE_REL_BASED_REL32 or RelocType.IMAGE_REL_BASED_RELPTR32 or RelocType.IMAGE_REL_BASED_ARM64_BRANCH26 && + relocType is IMAGE_REL_BASED_REL32 or IMAGE_REL_BASED_RELPTR32 or IMAGE_REL_BASED_ARM64_BRANCH26 + or IMAGE_REL_BASED_THUMB_BRANCH24 or IMAGE_REL_BASED_THUMB_MOV32_PCREL && _definedSymbols.TryGetValue(symbolName, out SymbolDefinition definedSymbol) && definedSymbol.SectionIndex == sectionIndex) { // Resolve the relocation to already defined symbol and write it into data - switch (relocType) + fixed (byte *pData = data) { - case RelocType.IMAGE_REL_BASED_REL32: - addend += BinaryPrimitives.ReadInt32LittleEndian(data); - addend -= 4; - BinaryPrimitives.WriteInt32LittleEndian(data, (int)(definedSymbol.Value - offset) + (int)addend); - return; - - case RelocType.IMAGE_REL_BASED_RELPTR32: - addend += BinaryPrimitives.ReadInt32LittleEndian(data); - BinaryPrimitives.WriteInt32LittleEndian(data, (int)(definedSymbol.Value - offset) + (int)addend); - return; - - case RelocType.IMAGE_REL_BASED_ARM64_BRANCH26: - var ins = BinaryPrimitives.ReadUInt32LittleEndian(data) & 0xFC000000; - BinaryPrimitives.WriteUInt32LittleEndian(data, (((uint)(int)(definedSymbol.Value - offset) >> 2) & 0x3FFFFFF) | ins); - return; + // RyuJIT generates the Thumb bit in the addend and we also get it from + // the symbol value. The AAELF ABI specification defines the R_ARM_THM_JUMP24 + // and R_ARM_THM_MOVW_PREL_NC relocations using the formula ((S + A) | T) – P. + // The thumb bit is thus supposed to be only added once. + // For R_ARM_THM_JUMP24 the thumb bit cannot be encoded, so mask it out. + long maskThumbBitOut = relocType is IMAGE_REL_BASED_THUMB_BRANCH24 or IMAGE_REL_BASED_THUMB_MOV32_PCREL ? 1 : 0; + long maskThumbBitIn = relocType is IMAGE_REL_BASED_THUMB_MOV32_PCREL ? 1 : 0; + + addend -= relocType switch + { + IMAGE_REL_BASED_REL32 => 4, + IMAGE_REL_BASED_THUMB_BRANCH24 => 4, + IMAGE_REL_BASED_THUMB_MOV32_PCREL => 12, + _ => 0 + }; + + addend += definedSymbol.Value & ~maskThumbBitOut; + addend += Relocation.ReadValue(relocType, (void*)pData); + addend |= definedSymbol.Value & maskThumbBitIn; + addend -= offset; + Relocation.WriteValue(relocType, (void*)pData, addend); } } - - EmitRelocation(sectionIndex, offset, data, relocType, symbolName, addend); + else + { + EmitRelocation(sectionIndex, offset, data, relocType, symbolName, addend); + } } /// @@ -386,19 +396,20 @@ private void EmitObject(string objectFilePath, IReadOnlyCollection false false + false false true diff --git a/src/coreclr/tools/aot/crossgen2/crossgen2_publish.csproj b/src/coreclr/tools/aot/crossgen2/crossgen2_publish.csproj index 2416920ed4055..b1c2a1835bfaa 100644 --- a/src/coreclr/tools/aot/crossgen2/crossgen2_publish.csproj +++ b/src/coreclr/tools/aot/crossgen2/crossgen2_publish.csproj @@ -10,6 +10,7 @@ false false + false false true diff --git a/src/native/external/llvm-libunwind/include/__libunwind_config.h b/src/native/external/llvm-libunwind/include/__libunwind_config.h index b925489e3e7fe..6fdc48ed30a29 100644 --- a/src/native/external/llvm-libunwind/include/__libunwind_config.h +++ b/src/native/external/llvm-libunwind/include/__libunwind_config.h @@ -14,6 +14,10 @@ #if defined(__arm__) && !defined(__USING_SJLJ_EXCEPTIONS__) && \ !defined(__ARM_DWARF_EH__) && !defined(__SEH__) #define _LIBUNWIND_ARM_EHABI +// Until ObjWriter is modified to convert DWARF to EHABI we want to +// support both. +#define _LIBUNWIND_SUPPORT_DWARF_UNWIND 1 +#define _LIBUNWIND_SUPPORT_DWARF_INDEX 1 #endif #define _LIBUNWIND_HIGHEST_DWARF_REGISTER_X86 8 diff --git a/src/tests/nativeaot/SmokeTests/PInvoke/PInvokeNative.cpp b/src/tests/nativeaot/SmokeTests/PInvoke/PInvokeNative.cpp index bd6bb32e0e1bb..6212c9b1b988d 100644 --- a/src/tests/nativeaot/SmokeTests/PInvoke/PInvokeNative.cpp +++ b/src/tests/nativeaot/SmokeTests/PInvoke/PInvokeNative.cpp @@ -318,9 +318,9 @@ DLL_EXPORT bool __stdcall ReleaseMemory(void *mem) return true; } -DLL_EXPORT bool __stdcall SafeHandleTest(HANDLE sh, long shValue) +DLL_EXPORT bool __stdcall SafeHandleTest(HANDLE sh, int64_t shValue) { - return (long)((size_t)(sh)) == shValue; + return (int64_t)((size_t)(sh)) == shValue; } DLL_EXPORT long __stdcall SafeHandleOutTest(HANDLE **sh)