From 6e92aed73f9c41757ea5659ab57ce1f0ea3e92cd Mon Sep 17 00:00:00 2001 From: Filip Navara Date: Tue, 16 Jan 2024 15:03:32 +0100 Subject: [PATCH 01/19] Mask thumb bit when setting IP in a context (eg. palContext->SetIp((uintptr_t)&RhpThrowHwEx)) --- src/coreclr/nativeaot/Runtime/EHHelpers.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/coreclr/nativeaot/Runtime/EHHelpers.cpp b/src/coreclr/nativeaot/Runtime/EHHelpers.cpp index f383ff688dad9..ad77294318b62 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 @@ -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); From ca93010870b0674ff0accf263a52130246dcf838 Mon Sep 17 00:00:00 2001 From: Filip Navara Date: Tue, 16 Jan 2024 15:04:10 +0100 Subject: [PATCH 02/19] Set ExInfo.m_pExContext in RhpThrowHwEx --- src/coreclr/nativeaot/Runtime/arm/ExceptionHandling.S | 4 ++++ 1 file changed, 4 insertions(+) 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 From e774599e036fc004fe13d6b6d74ff393a52e4d60 Mon Sep 17 00:00:00 2001 From: Filip Navara Date: Tue, 16 Jan 2024 15:05:40 +0100 Subject: [PATCH 03/19] Remove REGDISPLAY.GetAddrOfIP and it's only usage --- src/coreclr/nativeaot/Runtime/StackFrameIterator.cpp | 2 +- src/coreclr/nativeaot/Runtime/regdisplay.h | 4 ---- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/src/coreclr/nativeaot/Runtime/StackFrameIterator.cpp b/src/coreclr/nativeaot/Runtime/StackFrameIterator.cpp index 6e5b0fe1a0c13..9b5c9ef57709e 100644 --- a/src/coreclr/nativeaot/Runtime/StackFrameIterator.cpp +++ b/src/coreclr/nativeaot/Runtime/StackFrameIterator.cpp @@ -1355,7 +1355,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/regdisplay.h b/src/coreclr/nativeaot/Runtime/regdisplay.h index eae75eabe2e6c..2cf6374e2d3b2 100644 --- a/src/coreclr/nativeaot/Runtime/regdisplay.h +++ b/src/coreclr/nativeaot/Runtime/regdisplay.h @@ -41,7 +41,6 @@ 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; } @@ -80,7 +79,6 @@ 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; } @@ -135,7 +133,6 @@ 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; } @@ -154,7 +151,6 @@ struct REGDISPLAY 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; } From 0fcb0f378b237e04429ef0f737a969439fc5a04e Mon Sep 17 00:00:00 2001 From: Filip Navara Date: Tue, 16 Jan 2024 15:06:37 +0100 Subject: [PATCH 04/19] Resolve ARM relocations (also workarounds LLD bug with thumb bit present both in addend and in symbol value) --- .../Compiler/ObjectWriter/ElfObjectWriter.cs | 20 +++--- .../Compiler/ObjectWriter/ObjectWriter.cs | 61 +++++++++++-------- 2 files changed, 43 insertions(+), 38 deletions(-) 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..f40c9660f3053 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) { @@ -219,11 +214,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 Date: Tue, 16 Jan 2024 15:17:15 +0100 Subject: [PATCH 05/19] Remove REGDISPLAY.pIP/SetAddrOfIP --- .../nativeaot/Runtime/StackFrameIterator.cpp | 19 +++--------- .../nativeaot/Runtime/amd64/AsmOffsetsCpu.h | 12 ++++---- .../nativeaot/Runtime/arm/AsmOffsetsCpu.h | 14 ++++----- .../nativeaot/Runtime/arm64/AsmOffsetsCpu.h | 14 ++++----- src/coreclr/nativeaot/Runtime/regdisplay.h | 8 ----- .../nativeaot/Runtime/unix/UnwindHelpers.cpp | 30 +++---------------- .../Runtime/windows/CoffNativeCodeManager.cpp | 4 --- 7 files changed, 28 insertions(+), 73 deletions(-) diff --git a/src/coreclr/nativeaot/Runtime/StackFrameIterator.cpp b/src/coreclr/nativeaot/Runtime/StackFrameIterator.cpp index 9b5c9ef57709e..22a5211fbfa9b 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 // @@ -779,10 +773,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) || @@ -966,7 +959,6 @@ void StackFrameIterator::UnwindFuncletInvokeThunk() m_RegDisplay.pFP = SP++; - m_RegDisplay.SetAddrOfIP((PTR_PCODE)SP); m_RegDisplay.SetIP(*SP++); m_RegDisplay.pX19 = SP++; @@ -986,12 +978,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 +1161,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 +1252,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)); 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/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 2cf6374e2d3b2..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) @@ -46,7 +45,6 @@ struct REGDISPLAY 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; } }; @@ -70,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) @@ -82,7 +79,6 @@ struct REGDISPLAY 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; } }; @@ -123,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 @@ -137,7 +132,6 @@ struct REGDISPLAY 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) @@ -147,7 +141,6 @@ 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; } @@ -155,7 +148,6 @@ struct REGDISPLAY 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/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/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++) From a689b60819a9b5fca98523e020ba85a79af2e995 Mon Sep 17 00:00:00 2001 From: Filip Navara Date: Tue, 16 Jan 2024 18:15:17 +0100 Subject: [PATCH 06/19] Make most of the assembly code PIE compatible --- src/coreclr/nativeaot/Runtime/arm/GcProbe.S | 6 ++- .../Runtime/arm/InteropThunksHelpers.S | 2 +- src/coreclr/nativeaot/Runtime/arm/PInvoke.S | 3 +- .../nativeaot/Runtime/arm/StubDispatch.S | 2 +- .../Runtime/arm/UniversalTransition.S | 4 +- .../nativeaot/Runtime/arm/WriteBarriers.S | 42 +++++++------------ .../Runtime/unix/unixasmmacrosarm.inc | 11 ++++- 7 files changed, 33 insertions(+), 37 deletions(-) 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/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 From 195edde673b3cd37ac27308839b8465f3ab5248b Mon Sep 17 00:00:00 2001 From: Filip Navara Date: Tue, 16 Jan 2024 18:22:47 +0100 Subject: [PATCH 07/19] NativeAOT: Enable DFEATURE_64BIT_ALIGNMENT on linux-arm --- src/coreclr/nativeaot/Runtime/CMakeLists.txt | 3 +++ 1 file changed, 3 insertions(+) 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) From 5015d9f5edb4c6a2e14de9926933b128122df12b Mon Sep 17 00:00:00 2001 From: Filip Navara Date: Tue, 16 Jan 2024 18:28:06 +0100 Subject: [PATCH 08/19] Enable NativeAOT linux-arm build --- eng/Subsets.props | 1 + src/coreclr/CMakeLists.txt | 2 +- src/coreclr/tools/aot/ILCompiler/ILCompiler.csproj | 1 + src/coreclr/tools/aot/crossgen2/crossgen2_publish.csproj | 1 + 4 files changed, 4 insertions(+), 1 deletion(-) diff --git a/eng/Subsets.props b/eng/Subsets.props index 0f78725c3af98..e06e08d55531b 100644 --- a/eng/Subsets.props +++ b/eng/Subsets.props @@ -113,6 +113,7 @@ true + true true diff --git a/src/coreclr/CMakeLists.txt b/src/coreclr/CMakeLists.txt index ade1e03c92efd..a28a0013498b3 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_TARGET_LINUX AND CLR_CMAKE_HOST_ARCH_ARM)) add_subdirectory(nativeaot) endif() endif(NOT CLR_CROSS_COMPONENTS_BUILD) diff --git a/src/coreclr/tools/aot/ILCompiler/ILCompiler.csproj b/src/coreclr/tools/aot/ILCompiler/ILCompiler.csproj index d3ccae71ef5cb..abf322985a38a 100644 --- a/src/coreclr/tools/aot/ILCompiler/ILCompiler.csproj +++ b/src/coreclr/tools/aot/ILCompiler/ILCompiler.csproj @@ -13,6 +13,7 @@ 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..762da6afa315e 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 From 7888adea74eb39d34a81d83543283a9d8e3b6ab4 Mon Sep 17 00:00:00 2001 From: Filip Navara Date: Tue, 16 Jan 2024 18:31:30 +0100 Subject: [PATCH 09/19] Enable DWARF exception handling for linux-arm --- .../external/llvm-libunwind/include/__libunwind_config.h | 4 ++++ 1 file changed, 4 insertions(+) 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 From b24b06346c9706c3ca7e02d49d791ba173a62128 Mon Sep 17 00:00:00 2001 From: Filip Navara Date: Wed, 17 Jan 2024 11:42:21 +0100 Subject: [PATCH 10/19] Fix UnwindFuncletInvokeThunk to skip over r2 register saved on stack by RhpCallFilterFunclet --- src/coreclr/nativeaot/Runtime/StackFrameIterator.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/coreclr/nativeaot/Runtime/StackFrameIterator.cpp b/src/coreclr/nativeaot/Runtime/StackFrameIterator.cpp index 22a5211fbfa9b..23e237f106f2b 100644 --- a/src/coreclr/nativeaot/Runtime/StackFrameIterator.cpp +++ b/src/coreclr/nativeaot/Runtime/StackFrameIterator.cpp @@ -901,12 +901,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; From 59b6defae0c6073a91e3f065ff0a0a72b311e3df Mon Sep 17 00:00:00 2001 From: Filip Navara Date: Wed, 17 Jan 2024 13:17:47 +0100 Subject: [PATCH 11/19] Fix signature of P/Invoke native code in SafeHandleTest to match the managed one --- src/tests/nativeaot/SmokeTests/PInvoke/PInvokeNative.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) 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) From 563f56a9eaf263218879802b6ca73e7e801f9e55 Mon Sep 17 00:00:00 2001 From: Filip Navara Date: Wed, 17 Jan 2024 15:44:38 +0100 Subject: [PATCH 12/19] Implement missing StackFrameIterator::InternalInit code for ARM --- .../nativeaot/Runtime/StackFrameIterator.cpp | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/coreclr/nativeaot/Runtime/StackFrameIterator.cpp b/src/coreclr/nativeaot/Runtime/StackFrameIterator.cpp index 23e237f106f2b..1943aa2bcb6d7 100644 --- a/src/coreclr/nativeaot/Runtime/StackFrameIterator.cpp +++ b/src/coreclr/nativeaot/Runtime/StackFrameIterator.cpp @@ -605,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 From a92df1e9cc6a878b4c9ad0ef336b867c006a629b Mon Sep 17 00:00:00 2001 From: Filip Navara Date: Thu, 18 Jan 2024 13:04:17 +0100 Subject: [PATCH 13/19] Fix thumb bit masking in InInterfaceDispatchHelper --- src/coreclr/nativeaot/Runtime/EHHelpers.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/coreclr/nativeaot/Runtime/EHHelpers.cpp b/src/coreclr/nativeaot/Runtime/EHHelpers.cpp index ad77294318b62..957bab172f4f5 100644 --- a/src/coreclr/nativeaot/Runtime/EHHelpers.cpp +++ b/src/coreclr/nativeaot/Runtime/EHHelpers.cpp @@ -369,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 From efb788981aadfb2383425e9d4b4e3c472c93dd11 Mon Sep 17 00:00:00 2001 From: Filip Navara Date: Wed, 17 Jan 2024 20:57:43 +0100 Subject: [PATCH 14/19] Workaround: Ensure the Thumb bit is set when looking up method info in DWARF. We would fail to lookup methods at their first instruction otherwise. --- .../nativeaot/Runtime/unix/UnixNativeCodeManager.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) 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) From b41c7e41ed9a14ebca55998c2a3d92ca30d55bdd Mon Sep 17 00:00:00 2001 From: Filip Navara Date: Fri, 19 Jan 2024 08:05:26 +0100 Subject: [PATCH 15/19] Correctly convert the addend for IMAGE_REL_BASED_THUMB_MOV32[_PCREL] into the ELF relocations --- .../Compiler/ObjectWriter/ElfObjectWriter.cs | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) 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 f40c9660f3053..c680ffa33d75f 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/ObjectWriter/ElfObjectWriter.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/ObjectWriter/ElfObjectWriter.cs @@ -191,12 +191,22 @@ protected internal override unsafe void EmitRelocation( } else { - if (addend != 0) + if (relocType is IMAGE_REL_BASED_THUMB_MOV32_PCREL) + { + 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 = (long)((((uint)(addend + 4) & 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; } } From 90028c3378e7233a48df6eec22867b1198ad419e Mon Sep 17 00:00:00 2001 From: Filip Navara Date: Fri, 19 Jan 2024 11:00:53 +0100 Subject: [PATCH 16/19] Simplify CMake condition --- src/coreclr/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/coreclr/CMakeLists.txt b/src/coreclr/CMakeLists.txt index a28a0013498b3..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 OR (CLR_CMAKE_TARGET_LINUX AND CLR_CMAKE_HOST_ARCH_ARM)) + 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) From b242d0d3e6320423a40cc5c70a5f56ca844932e2 Mon Sep 17 00:00:00 2001 From: Filip Navara Date: Fri, 19 Jan 2024 12:05:17 +0100 Subject: [PATCH 17/19] Simplify NativeAotSupported conditions --- eng/Subsets.props | 3 +-- src/coreclr/tools/aot/ILCompiler/ILCompiler.csproj | 2 +- src/coreclr/tools/aot/crossgen2/crossgen2_publish.csproj | 2 +- 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/eng/Subsets.props b/eng/Subsets.props index e06e08d55531b..b769e1c18a0d6 100644 --- a/eng/Subsets.props +++ b/eng/Subsets.props @@ -112,8 +112,7 @@ - true - true + true true diff --git a/src/coreclr/tools/aot/ILCompiler/ILCompiler.csproj b/src/coreclr/tools/aot/ILCompiler/ILCompiler.csproj index abf322985a38a..c7c8eaf91c38f 100644 --- a/src/coreclr/tools/aot/ILCompiler/ILCompiler.csproj +++ b/src/coreclr/tools/aot/ILCompiler/ILCompiler.csproj @@ -13,7 +13,7 @@ false 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 762da6afa315e..9ccc5275ee7aa 100644 --- a/src/coreclr/tools/aot/crossgen2/crossgen2_publish.csproj +++ b/src/coreclr/tools/aot/crossgen2/crossgen2_publish.csproj @@ -10,7 +10,7 @@ false false - false + false false true From 5e70f46a0eda22f9bee7478f02de807dc5eff69e Mon Sep 17 00:00:00 2001 From: Filip Navara Date: Fri, 19 Jan 2024 12:40:27 +0100 Subject: [PATCH 18/19] Fix typo --- src/coreclr/tools/aot/ILCompiler/ILCompiler.csproj | 2 +- src/coreclr/tools/aot/crossgen2/crossgen2_publish.csproj | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/coreclr/tools/aot/ILCompiler/ILCompiler.csproj b/src/coreclr/tools/aot/ILCompiler/ILCompiler.csproj index c7c8eaf91c38f..838bd77c13309 100644 --- a/src/coreclr/tools/aot/ILCompiler/ILCompiler.csproj +++ b/src/coreclr/tools/aot/ILCompiler/ILCompiler.csproj @@ -13,7 +13,7 @@ false 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 9ccc5275ee7aa..b1c2a1835bfaa 100644 --- a/src/coreclr/tools/aot/crossgen2/crossgen2_publish.csproj +++ b/src/coreclr/tools/aot/crossgen2/crossgen2_publish.csproj @@ -10,7 +10,7 @@ false false - false + false false true From 07b6dcdd54623bda04e2d3a2290c19e6936c0b81 Mon Sep 17 00:00:00 2001 From: Filip Navara Date: Fri, 19 Jan 2024 12:57:49 +0100 Subject: [PATCH 19/19] Fix IMAGE_REL_BASED_THUMB_MOV32 conversion to ELF --- .../Compiler/ObjectWriter/ElfObjectWriter.cs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) 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 c680ffa33d75f..aa4b39552b693 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/ObjectWriter/ElfObjectWriter.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/ObjectWriter/ElfObjectWriter.cs @@ -191,14 +191,16 @@ protected internal override unsafe void EmitRelocation( } else { - if (relocType is IMAGE_REL_BASED_THUMB_MOV32_PCREL) + 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 = (long)((((uint)(addend + 4) & 0xffff) << 16) + (ushort)addend); + 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)