From ca95d4b332dc47e750bc8c83747ab07ad8b83543 Mon Sep 17 00:00:00 2001 From: Filip Navara Date: Wed, 31 Aug 2022 19:48:48 +0200 Subject: [PATCH 01/19] Enable NativeAOT osx-arm64 builds --- eng/Subsets.props | 2 +- src/coreclr/CMakeLists.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/eng/Subsets.props b/eng/Subsets.props index 0ccf99e83f7223..1f4987bfc30c8f 100644 --- a/eng/Subsets.props +++ b/eng/Subsets.props @@ -99,7 +99,7 @@ - true + true true diff --git a/src/coreclr/CMakeLists.txt b/src/coreclr/CMakeLists.txt index 7d1ce8d705d3d6..c28c30514832df 100644 --- a/src/coreclr/CMakeLists.txt +++ b/src/coreclr/CMakeLists.txt @@ -139,7 +139,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_LINUX OR CLR_CMAKE_HOST_OSX OR CLR_CMAKE_HOST_WIN32) AND (CLR_CMAKE_HOST_ARCH_ARM64 OR CLR_CMAKE_HOST_ARCH_AMD64) AND NOT (CLR_CMAKE_HOST_OSX AND CLR_CMAKE_HOST_ARCH_ARM64)) + if((CLR_CMAKE_HOST_LINUX OR CLR_CMAKE_HOST_OSX OR CLR_CMAKE_HOST_WIN32) AND (CLR_CMAKE_HOST_ARCH_ARM64 OR CLR_CMAKE_HOST_ARCH_AMD64)) add_subdirectory(nativeaot) endif() endif(NOT CLR_CROSS_COMPONENTS_BUILD) From 35a40f06772729b8972569762a83cb9a09928c05 Mon Sep 17 00:00:00 2001 From: Filip Navara Date: Wed, 31 Aug 2022 19:49:16 +0200 Subject: [PATCH 02/19] Restrict alignment in VirtualReserveInner --- src/coreclr/gc/unix/gcenv.unix.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/coreclr/gc/unix/gcenv.unix.cpp b/src/coreclr/gc/unix/gcenv.unix.cpp index 85d6a001b03822..a250b528d8096e 100644 --- a/src/coreclr/gc/unix/gcenv.unix.cpp +++ b/src/coreclr/gc/unix/gcenv.unix.cpp @@ -633,7 +633,7 @@ void GCToOSInterface::YieldThread(uint32_t switchCount) static void* VirtualReserveInner(size_t size, size_t alignment, uint32_t flags, uint32_t hugePagesFlag = 0) { assert(!(flags & VirtualReserveFlags::WriteWatch) && "WriteWatch not supported on Unix"); - if (alignment == 0) + if (alignment < OS_PAGE_SIZE) { alignment = OS_PAGE_SIZE; } From 387b31bedbf3483619359fee39cbd14965560b86 Mon Sep 17 00:00:00 2001 From: Filip Navara Date: Wed, 31 Aug 2022 19:51:39 +0200 Subject: [PATCH 03/19] Fix generation and handling of compact unwinding info on osx-arm64 --- .../nativeaot/Runtime/unix/UnwindHelpers.cpp | 224 +++++++++++++++++- 1 file changed, 223 insertions(+), 1 deletion(-) diff --git a/src/coreclr/nativeaot/Runtime/unix/UnwindHelpers.cpp b/src/coreclr/nativeaot/Runtime/unix/UnwindHelpers.cpp index bcc11718d704e4..72f448ed76e999 100644 --- a/src/coreclr/nativeaot/Runtime/unix/UnwindHelpers.cpp +++ b/src/coreclr/nativeaot/Runtime/unix/UnwindHelpers.cpp @@ -755,6 +755,206 @@ void Registers_REGDISPLAY::setVectorRegister(int num, libunwind::v128 value) D[num] = (uint64_t)value.vec[2] << 32 | (uint64_t)value.vec[3]; } +/// CompactUnwinder_arm64 uses a compact unwind info to virtually "step" (aka +/// unwind) by modifying a Registers_arm64 register set +template +class CompactUnwinder_arm64 { +public: + + static int stepWithCompactEncoding(compact_unwind_encoding_t compactEncoding, + uint64_t functionStart, A &addressSpace, + Registers_REGDISPLAY ®isters); + +private: + typename A::pint_t pint_t; + + static int + stepWithCompactEncodingFrame(compact_unwind_encoding_t compactEncoding, + uint64_t functionStart, A &addressSpace, + Registers_REGDISPLAY ®isters); + static int stepWithCompactEncodingFrameless( + compact_unwind_encoding_t compactEncoding, uint64_t functionStart, + A &addressSpace, Registers_REGDISPLAY ®isters); +}; + +template +int CompactUnwinder_arm64::stepWithCompactEncoding( + compact_unwind_encoding_t compactEncoding, uint64_t functionStart, + A &addressSpace, Registers_REGDISPLAY ®isters) { + switch (compactEncoding & UNWIND_ARM64_MODE_MASK) { + case UNWIND_ARM64_MODE_FRAME: + return stepWithCompactEncodingFrame(compactEncoding, functionStart, + addressSpace, registers); + case UNWIND_ARM64_MODE_FRAMELESS: + return stepWithCompactEncodingFrameless(compactEncoding, functionStart, + addressSpace, registers); + } + _LIBUNWIND_ABORT("invalid compact unwind encoding"); +} + +template +int CompactUnwinder_arm64::stepWithCompactEncodingFrameless( + compact_unwind_encoding_t encoding, uint64_t, A &addressSpace, + Registers_REGDISPLAY ®isters) { + uint32_t stackSize = + 16 * EXTRACT_BITS(encoding, UNWIND_ARM64_FRAMELESS_STACK_SIZE_MASK); + + uint64_t savedRegisterLoc = registers.getSP() + stackSize; + + if (encoding & UNWIND_ARM64_FRAME_X19_X20_PAIR) { + registers.setRegister(UNW_AARCH64_X19, addressSpace.get64(savedRegisterLoc), savedRegisterLoc); + savedRegisterLoc -= 8; + registers.setRegister(UNW_AARCH64_X20, addressSpace.get64(savedRegisterLoc), savedRegisterLoc); + savedRegisterLoc -= 8; + } + if (encoding & UNWIND_ARM64_FRAME_X21_X22_PAIR) { + registers.setRegister(UNW_AARCH64_X21, addressSpace.get64(savedRegisterLoc), savedRegisterLoc); + savedRegisterLoc -= 8; + registers.setRegister(UNW_AARCH64_X22, addressSpace.get64(savedRegisterLoc), savedRegisterLoc); + savedRegisterLoc -= 8; + } + if (encoding & UNWIND_ARM64_FRAME_X23_X24_PAIR) { + registers.setRegister(UNW_AARCH64_X23, addressSpace.get64(savedRegisterLoc), savedRegisterLoc); + savedRegisterLoc -= 8; + registers.setRegister(UNW_AARCH64_X24, addressSpace.get64(savedRegisterLoc), savedRegisterLoc); + savedRegisterLoc -= 8; + } + if (encoding & UNWIND_ARM64_FRAME_X25_X26_PAIR) { + registers.setRegister(UNW_AARCH64_X25, addressSpace.get64(savedRegisterLoc), savedRegisterLoc); + savedRegisterLoc -= 8; + registers.setRegister(UNW_AARCH64_X26, addressSpace.get64(savedRegisterLoc), savedRegisterLoc); + savedRegisterLoc -= 8; + } + if (encoding & UNWIND_ARM64_FRAME_X27_X28_PAIR) { + registers.setRegister(UNW_AARCH64_X27, addressSpace.get64(savedRegisterLoc), savedRegisterLoc); + savedRegisterLoc -= 8; + registers.setRegister(UNW_AARCH64_X28, addressSpace.get64(savedRegisterLoc), savedRegisterLoc); + savedRegisterLoc -= 8; + } + + if (encoding & UNWIND_ARM64_FRAME_D8_D9_PAIR) { + registers.setFloatRegister(UNW_AARCH64_V8, + addressSpace.getDouble(savedRegisterLoc)); + savedRegisterLoc -= 8; + registers.setFloatRegister(UNW_AARCH64_V9, + addressSpace.getDouble(savedRegisterLoc)); + savedRegisterLoc -= 8; + } + if (encoding & UNWIND_ARM64_FRAME_D10_D11_PAIR) { + registers.setFloatRegister(UNW_AARCH64_V10, + addressSpace.getDouble(savedRegisterLoc)); + savedRegisterLoc -= 8; + registers.setFloatRegister(UNW_AARCH64_V11, + addressSpace.getDouble(savedRegisterLoc)); + savedRegisterLoc -= 8; + } + if (encoding & UNWIND_ARM64_FRAME_D12_D13_PAIR) { + registers.setFloatRegister(UNW_AARCH64_V12, + addressSpace.getDouble(savedRegisterLoc)); + savedRegisterLoc -= 8; + registers.setFloatRegister(UNW_AARCH64_V13, + addressSpace.getDouble(savedRegisterLoc)); + savedRegisterLoc -= 8; + } + if (encoding & UNWIND_ARM64_FRAME_D14_D15_PAIR) { + registers.setFloatRegister(UNW_AARCH64_V14, + addressSpace.getDouble(savedRegisterLoc)); + savedRegisterLoc -= 8; + registers.setFloatRegister(UNW_AARCH64_V15, + addressSpace.getDouble(savedRegisterLoc)); + savedRegisterLoc -= 8; + } + + // subtract stack size off of sp + registers.setSP(savedRegisterLoc, 0); + + // set pc to be value in lr + registers.setIP(registers.getRegister(UNW_AARCH64_LR), 0); + + return UNW_STEP_SUCCESS; +} + +template +int CompactUnwinder_arm64::stepWithCompactEncodingFrame( + compact_unwind_encoding_t encoding, uint64_t, A &addressSpace, + Registers_REGDISPLAY ®isters) { + uint64_t savedRegisterLoc = registers.GetFP() - 8; + + if (encoding & UNWIND_ARM64_FRAME_X19_X20_PAIR) { + registers.setRegister(UNW_AARCH64_X19, addressSpace.get64(savedRegisterLoc), savedRegisterLoc); + savedRegisterLoc -= 8; + registers.setRegister(UNW_AARCH64_X20, addressSpace.get64(savedRegisterLoc), savedRegisterLoc); + savedRegisterLoc -= 8; + } + if (encoding & UNWIND_ARM64_FRAME_X21_X22_PAIR) { + registers.setRegister(UNW_AARCH64_X21, addressSpace.get64(savedRegisterLoc), savedRegisterLoc); + savedRegisterLoc -= 8; + registers.setRegister(UNW_AARCH64_X22, addressSpace.get64(savedRegisterLoc), savedRegisterLoc); + savedRegisterLoc -= 8; + } + if (encoding & UNWIND_ARM64_FRAME_X23_X24_PAIR) { + registers.setRegister(UNW_AARCH64_X23, addressSpace.get64(savedRegisterLoc), savedRegisterLoc); + savedRegisterLoc -= 8; + registers.setRegister(UNW_AARCH64_X24, addressSpace.get64(savedRegisterLoc), savedRegisterLoc); + savedRegisterLoc -= 8; + } + if (encoding & UNWIND_ARM64_FRAME_X25_X26_PAIR) { + registers.setRegister(UNW_AARCH64_X25, addressSpace.get64(savedRegisterLoc), savedRegisterLoc); + savedRegisterLoc -= 8; + registers.setRegister(UNW_AARCH64_X26, addressSpace.get64(savedRegisterLoc), savedRegisterLoc); + savedRegisterLoc -= 8; + } + if (encoding & UNWIND_ARM64_FRAME_X27_X28_PAIR) { + registers.setRegister(UNW_AARCH64_X27, addressSpace.get64(savedRegisterLoc), savedRegisterLoc); + savedRegisterLoc -= 8; + registers.setRegister(UNW_AARCH64_X28, addressSpace.get64(savedRegisterLoc), savedRegisterLoc); + savedRegisterLoc -= 8; + } + + if (encoding & UNWIND_ARM64_FRAME_D8_D9_PAIR) { + registers.setFloatRegister(UNW_AARCH64_V8, + addressSpace.getDouble(savedRegisterLoc)); + savedRegisterLoc -= 8; + registers.setFloatRegister(UNW_AARCH64_V9, + addressSpace.getDouble(savedRegisterLoc)); + savedRegisterLoc -= 8; + } + if (encoding & UNWIND_ARM64_FRAME_D10_D11_PAIR) { + registers.setFloatRegister(UNW_AARCH64_V10, + addressSpace.getDouble(savedRegisterLoc)); + savedRegisterLoc -= 8; + registers.setFloatRegister(UNW_AARCH64_V11, + addressSpace.getDouble(savedRegisterLoc)); + savedRegisterLoc -= 8; + } + if (encoding & UNWIND_ARM64_FRAME_D12_D13_PAIR) { + registers.setFloatRegister(UNW_AARCH64_V12, + addressSpace.getDouble(savedRegisterLoc)); + savedRegisterLoc -= 8; + registers.setFloatRegister(UNW_AARCH64_V13, + addressSpace.getDouble(savedRegisterLoc)); + savedRegisterLoc -= 8; + } + if (encoding & UNWIND_ARM64_FRAME_D14_D15_PAIR) { + registers.setFloatRegister(UNW_AARCH64_V14, + addressSpace.getDouble(savedRegisterLoc)); + savedRegisterLoc -= 8; + registers.setFloatRegister(UNW_AARCH64_V15, + addressSpace.getDouble(savedRegisterLoc)); + savedRegisterLoc -= 8; + } + + uint64_t fp = registers.GetFP(); + // fp points to old fp + registers.setRegister(UNW_ARM64_FP, addressSpace.get64(fp), fp); + // old sp is fp less saved fp and lr + registers.setSP(fp + 16, 0); + // pop return address into pc + registers.setIP(addressSpace.get64(fp + 8), fp + 8); + + return UNW_STEP_SUCCESS; +} + #endif // TARGET_ARM64 bool DoTheStep(uintptr_t pc, UnwindInfoSections uwInfoSections, REGDISPLAY *regs) @@ -772,7 +972,29 @@ bool DoTheStep(uintptr_t pc, UnwindInfoSections uwInfoSections, REGDISPLAY *regs #endif #if _LIBUNWIND_SUPPORT_DWARF_UNWIND - bool retVal = uc.getInfoFromDwarfSection(pc, uwInfoSections, 0 /* fdeSectionOffsetHint */); + uint32_t dwarfOffsetHint = 0; + +#if _LIBUNWIND_SUPPORT_COMPACT_UNWIND + // If there is a compact unwind encoding table, look there first. + if (uwInfoSections.compact_unwind_section != 0 && uc.getInfoFromCompactEncodingSection(pc, uwInfoSections)) { + unw_proc_info_t procInfo; + uc.getInfo(&procInfo); + +#if defined(_LIBUNWIND_TARGET_AARCH64) + if ((procInfo.format & UNWIND_ARM64_MODE_MASK) != UNWIND_ARM64_MODE_DWARF) { + CompactUnwinder_arm64 compactInst; + int stepRet = compactInst.stepWithCompactEncoding(procInfo.format, pc, _addressSpace, *(Registers_REGDISPLAY*)regs); + return stepRet == UNW_STEP_SUCCESS; + } else { + dwarfOffsetHint = procInfo.format & UNWIND_X86_64_DWARF_SECTION_OFFSET; + } +#else + PORTABILITY_ASSERT("DoTheStep"); +#endif + } +#endif + + bool retVal = uc.getInfoFromDwarfSection(pc, uwInfoSections, dwarfOffsetHint); if (!retVal) { return false; From 50eb6f6d045addefd2add80a72de993748706afc Mon Sep 17 00:00:00 2001 From: Filip Navara Date: Tue, 6 Sep 2022 17:18:16 +0200 Subject: [PATCH 04/19] Fix PC check in findFDE in DWARF CFI unwinding --- src/native/external/llvm-libunwind/src/DwarfParser.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/native/external/llvm-libunwind/src/DwarfParser.hpp b/src/native/external/llvm-libunwind/src/DwarfParser.hpp index 3c8a5d5caa8e78..0a57f69a62745c 100644 --- a/src/native/external/llvm-libunwind/src/DwarfParser.hpp +++ b/src/native/external/llvm-libunwind/src/DwarfParser.hpp @@ -269,7 +269,7 @@ bool CFI_Parser::findFDE(A &addressSpace, pint_t pc, pint_t ehSectionStart, pint_t pcRange = addressSpace.getEncodedP( p, nextCFI, cieInfo->pointerEncoding & 0x0F); // Test if pc is within the function this FDE covers. - if ((pcStart < pc) && (pc <= pcStart + pcRange)) { + if ((pcStart <= pc) && (pc < pcStart + pcRange)) { // parse rest of info fdeInfo->lsda = 0; // check for augmentation length From cb81686547cfc54b8bf53c96f163d7bfbfc4bebc Mon Sep 17 00:00:00 2001 From: Filip Navara Date: Wed, 7 Sep 2022 22:48:39 +0200 Subject: [PATCH 05/19] Handle MAP_JIT for P/Invoke on osx-arm64 --- .../src/System/Runtime/InternalCalls.cs | 4 +++ .../src/System/Runtime/ThunkPool.cs | 35 ++++++++++++++++++- .../nativeaot/Runtime/ThunksMapping.cpp | 13 +++++++ .../nativeaot/Runtime/unix/PalRedhawkUnix.cpp | 9 ++++- 4 files changed, 59 insertions(+), 2 deletions(-) diff --git a/src/coreclr/nativeaot/Runtime.Base/src/System/Runtime/InternalCalls.cs b/src/coreclr/nativeaot/Runtime.Base/src/System/Runtime/InternalCalls.cs index 9cfde639cb60b7..8c68a2ebe0690e 100644 --- a/src/coreclr/nativeaot/Runtime.Base/src/System/Runtime/InternalCalls.cs +++ b/src/coreclr/nativeaot/Runtime.Base/src/System/Runtime/InternalCalls.cs @@ -321,6 +321,10 @@ internal static extern unsafe bool RhpCallFilterFunclet( [UnmanagedCallConv(CallConvs = new Type[] { typeof(CallConvCdecl) })] internal static extern IntPtr RhAllocateThunksMapping(); + [DllImport(Redhawk.BaseName)] + [UnmanagedCallConv(CallConvs = new Type[] { typeof(CallConvCdecl) })] + internal static extern void RhJitWriteProtect(int writeEnable); + // Enters a no GC region, possibly doing a blocking GC if there is not enough // memory available to satisfy the caller's request. [DllImport(Redhawk.BaseName)] diff --git a/src/coreclr/nativeaot/Runtime.Base/src/System/Runtime/ThunkPool.cs b/src/coreclr/nativeaot/Runtime.Base/src/System/Runtime/ThunkPool.cs index b08af54b5bfc21..a00ebf07e2b717 100644 --- a/src/coreclr/nativeaot/Runtime.Base/src/System/Runtime/ThunkPool.cs +++ b/src/coreclr/nativeaot/Runtime.Base/src/System/Runtime/ThunkPool.cs @@ -40,9 +40,14 @@ namespace System.Runtime { internal static class Constants { +#if TARGET_ARM64 && TARGET_OSX + public const uint PageSize = 0x4000; // 16k + public const nuint PageSizeMask = 0x3FFF; +#else public const uint PageSize = 0x1000; // 4k - public const uint AllocationGranularity = 0x10000; // 64k public const nuint PageSizeMask = 0xFFF; +#endif + public const uint AllocationGranularity = 0x10000; // 64k public const nuint AllocationGranularityMask = 0xFFFF; public static readonly int ThunkDataSize = 2 * IntPtr.Size; @@ -102,10 +107,14 @@ private unsafe ThunksHeap(IntPtr commonStubAddress) // Address of the first thunk data cell should be at the beginning of the thunks data block (page-aligned) Debug.Assert(((nuint)(nint)thunkDataBlock % Constants.PageSize) == 0); + InternalCalls.RhJitWriteProtect(0); + // Update the last pointer value in the thunks data section with the value of the common stub address *(IntPtr*)(thunkDataBlock + (int)(Constants.PageSize - IntPtr.Size)) = commonStubAddress; Debug.Assert(*(IntPtr*)(thunkDataBlock + (int)(Constants.PageSize - IntPtr.Size)) == commonStubAddress); + InternalCalls.RhJitWriteProtect(1); + // Set the head and end of the linked list _nextAvailableThunkPtr = thunkDataBlock; _lastThunkPtr = _nextAvailableThunkPtr + Constants.ThunkDataSize * (Constants.NumThunksPerBlock - 1); @@ -158,6 +167,8 @@ private unsafe bool ExpandHeap() // Address of the first thunk data cell should be at the beginning of the thunks data block (page-aligned) Debug.Assert(((nuint)(nint)thunkDataBlock % Constants.PageSize) == 0); + InternalCalls.RhJitWriteProtect(0); + // Update the last pointer value in the thunks data section with the value of the common stub address *(IntPtr*)(thunkDataBlock + (int)(Constants.PageSize - IntPtr.Size)) = _commonStubAddress; Debug.Assert(*(IntPtr*)(thunkDataBlock + (int)(Constants.PageSize - IntPtr.Size)) == _commonStubAddress); @@ -168,6 +179,8 @@ private unsafe bool ExpandHeap() // Update the pointer to the last entry in the list _lastThunkPtr = *((IntPtr*)_lastThunkPtr) + Constants.ThunkDataSize * (Constants.NumThunksPerBlock - 1); + InternalCalls.RhJitWriteProtect(1); + newBlockInfo._blockBaseAddress = thunkStubsBlock; newBlockInfo._nextBlock = _allocatedBlocks; @@ -211,8 +224,10 @@ public unsafe IntPtr AllocateThunk() Debug.Assert(nextAvailableThunkPtr != IntPtr.Zero); #if DEBUG + InternalCalls.RhJitWriteProtect(0); // Reset debug flag indicating the thunk is now in use *((IntPtr*)(nextAvailableThunkPtr + IntPtr.Size)) = IntPtr.Zero; + InternalCalls.RhJitWriteProtect(1); #endif int thunkIndex = (int)(((nuint)(nint)nextAvailableThunkPtr) - ((nuint)(nint)nextAvailableThunkPtr & ~Constants.PageSizeMask)); @@ -237,8 +252,12 @@ public unsafe void FreeThunk(IntPtr thunkAddress) if (!IsThunkInHeap(thunkAddress)) EH.FallbackFailFast(RhFailFastReason.InternalError, null); + InternalCalls.RhJitWriteProtect(0); + // Debug flag indicating the thunk is no longer used *((IntPtr*)(dataAddress + IntPtr.Size)) = new IntPtr(-1); +#else + InternalCalls.RhJitWriteProtect(0); #endif InternalCalls.RhpAcquireThunkPoolLock(); @@ -247,6 +266,8 @@ public unsafe void FreeThunk(IntPtr thunkAddress) _nextAvailableThunkPtr = dataAddress; InternalCalls.RhpReleaseThunkPoolLock(); + + InternalCalls.RhJitWriteProtect(1); } private bool IsThunkInHeap(IntPtr thunkAddress) @@ -308,10 +329,14 @@ public unsafe bool TryGetThunkData(IntPtr thunkAddress, out IntPtr context, out if (!IsThunkInHeap(thunkAddress)) return false; + InternalCalls.RhJitWriteProtect(0); + // Update the data that will be used by the thunk that was allocated context = *((IntPtr*)(dataAddress)); target = *((IntPtr*)(dataAddress + IntPtr.Size)); + InternalCalls.RhJitWriteProtect(1); + return true; } @@ -332,9 +357,13 @@ public unsafe void SetThunkData(IntPtr thunkAddress, IntPtr context, IntPtr targ EH.FallbackFailFast(RhFailFastReason.InternalError, null); #endif + InternalCalls.RhJitWriteProtect(0); + // Update the data that will be used by the thunk that was allocated *((IntPtr*)(dataAddress)) = context; *((IntPtr*)(dataAddress + IntPtr.Size)) = target; + + InternalCalls.RhJitWriteProtect(1); } } @@ -391,6 +420,8 @@ public static unsafe IntPtr GetNewThunksBlock() // Use the first data field of the thunk to build the linked list. IntPtr dataAddress = InternalCalls.RhpGetThunkDataBlockAddress(nextThunksBlock); + InternalCalls.RhJitWriteProtect(0); + for (int i = 0; i < Constants.NumThunksPerBlock; i++) { if (i == (Constants.NumThunksPerBlock - 1)) @@ -406,6 +437,8 @@ public static unsafe IntPtr GetNewThunksBlock() dataAddress += Constants.ThunkDataSize; } + InternalCalls.RhJitWriteProtect(1); + return nextThunksBlock; } diff --git a/src/coreclr/nativeaot/Runtime/ThunksMapping.cpp b/src/coreclr/nativeaot/Runtime/ThunksMapping.cpp index 760dbc3b0ad8e7..c2a74a6c7a0d0e 100644 --- a/src/coreclr/nativeaot/Runtime/ThunksMapping.cpp +++ b/src/coreclr/nativeaot/Runtime/ThunksMapping.cpp @@ -89,6 +89,13 @@ COOP_PINVOKE_HELPER(int, RhpGetThunkBlockSize, ()) return OS_PAGE_SIZE; } +EXTERN_C NATIVEAOT_API void __cdecl RhJitWriteProtect(int writeEnable) +{ +#if defined(HOST_OSX) && defined(HOST_ARM64) + pthread_jit_write_protect_np(writeEnable); +#endif +} + EXTERN_C NATIVEAOT_API void* __cdecl RhAllocateThunksMapping() { #ifdef WIN32 @@ -121,6 +128,8 @@ EXTERN_C NATIVEAOT_API void* __cdecl RhAllocateThunksMapping() return NULL; } + RhJitWriteProtect(0); + #endif int numBlocksPerMap = RhpGetNumThunkBlocksPerMapping(); @@ -223,11 +232,15 @@ EXTERN_C NATIVEAOT_API void* __cdecl RhAllocateThunksMapping() } } +#if defined(HOST_OSX) && defined(HOST_ARM64) + RhJitWriteProtect(1); +#else if (!PalVirtualProtect(pThunksSection, THUNKS_MAP_SIZE, PAGE_EXECUTE_READ)) { PalVirtualFree(pNewMapping, 0, MEM_RELEASE); return NULL; } +#endif PalFlushInstructionCache(pThunksSection, THUNKS_MAP_SIZE); diff --git a/src/coreclr/nativeaot/Runtime/unix/PalRedhawkUnix.cpp b/src/coreclr/nativeaot/Runtime/unix/PalRedhawkUnix.cpp index 55ad31c82d886a..7a49115ae413d2 100644 --- a/src/coreclr/nativeaot/Runtime/unix/PalRedhawkUnix.cpp +++ b/src/coreclr/nativeaot/Runtime/unix/PalRedhawkUnix.cpp @@ -776,8 +776,15 @@ REDHAWK_PALEXPORT _Ret_maybenull_ _Post_writable_byte_size_(size) void* REDHAWK_ static const size_t Alignment = 64 * 1024; size_t alignedSize = size + (Alignment - OS_PAGE_SIZE); + int flags = MAP_ANON | MAP_PRIVATE; - void * pRetVal = mmap(pAddress, alignedSize, unixProtect, MAP_ANON | MAP_PRIVATE, -1, 0); +#if defined(HOST_OSX) && defined(HOST_ARM64) + if (unixProtect & PROT_EXEC) { + flags |= MAP_JIT; + } +#endif + + void * pRetVal = mmap(pAddress, alignedSize, unixProtect, flags, -1, 0); if (pRetVal != NULL) { From 69fd921dbbf1ecb45b30b763e92aa1ff089decf9 Mon Sep 17 00:00:00 2001 From: Filip Navara Date: Thu, 8 Sep 2022 00:11:25 +0200 Subject: [PATCH 06/19] Handle P/Invoke with MAP_JIT on osx-arm64 --- .../src/System/Runtime/InternalCalls.cs | 4 --- .../src/System/Runtime/ThunkPool.cs | 28 ------------------- .../nativeaot/Runtime/ThunksMapping.cpp | 15 ++++------ 3 files changed, 5 insertions(+), 42 deletions(-) diff --git a/src/coreclr/nativeaot/Runtime.Base/src/System/Runtime/InternalCalls.cs b/src/coreclr/nativeaot/Runtime.Base/src/System/Runtime/InternalCalls.cs index 8c68a2ebe0690e..9cfde639cb60b7 100644 --- a/src/coreclr/nativeaot/Runtime.Base/src/System/Runtime/InternalCalls.cs +++ b/src/coreclr/nativeaot/Runtime.Base/src/System/Runtime/InternalCalls.cs @@ -321,10 +321,6 @@ internal static extern unsafe bool RhpCallFilterFunclet( [UnmanagedCallConv(CallConvs = new Type[] { typeof(CallConvCdecl) })] internal static extern IntPtr RhAllocateThunksMapping(); - [DllImport(Redhawk.BaseName)] - [UnmanagedCallConv(CallConvs = new Type[] { typeof(CallConvCdecl) })] - internal static extern void RhJitWriteProtect(int writeEnable); - // Enters a no GC region, possibly doing a blocking GC if there is not enough // memory available to satisfy the caller's request. [DllImport(Redhawk.BaseName)] diff --git a/src/coreclr/nativeaot/Runtime.Base/src/System/Runtime/ThunkPool.cs b/src/coreclr/nativeaot/Runtime.Base/src/System/Runtime/ThunkPool.cs index a00ebf07e2b717..73bc32ffe36547 100644 --- a/src/coreclr/nativeaot/Runtime.Base/src/System/Runtime/ThunkPool.cs +++ b/src/coreclr/nativeaot/Runtime.Base/src/System/Runtime/ThunkPool.cs @@ -107,14 +107,10 @@ private unsafe ThunksHeap(IntPtr commonStubAddress) // Address of the first thunk data cell should be at the beginning of the thunks data block (page-aligned) Debug.Assert(((nuint)(nint)thunkDataBlock % Constants.PageSize) == 0); - InternalCalls.RhJitWriteProtect(0); - // Update the last pointer value in the thunks data section with the value of the common stub address *(IntPtr*)(thunkDataBlock + (int)(Constants.PageSize - IntPtr.Size)) = commonStubAddress; Debug.Assert(*(IntPtr*)(thunkDataBlock + (int)(Constants.PageSize - IntPtr.Size)) == commonStubAddress); - InternalCalls.RhJitWriteProtect(1); - // Set the head and end of the linked list _nextAvailableThunkPtr = thunkDataBlock; _lastThunkPtr = _nextAvailableThunkPtr + Constants.ThunkDataSize * (Constants.NumThunksPerBlock - 1); @@ -167,8 +163,6 @@ private unsafe bool ExpandHeap() // Address of the first thunk data cell should be at the beginning of the thunks data block (page-aligned) Debug.Assert(((nuint)(nint)thunkDataBlock % Constants.PageSize) == 0); - InternalCalls.RhJitWriteProtect(0); - // Update the last pointer value in the thunks data section with the value of the common stub address *(IntPtr*)(thunkDataBlock + (int)(Constants.PageSize - IntPtr.Size)) = _commonStubAddress; Debug.Assert(*(IntPtr*)(thunkDataBlock + (int)(Constants.PageSize - IntPtr.Size)) == _commonStubAddress); @@ -179,8 +173,6 @@ private unsafe bool ExpandHeap() // Update the pointer to the last entry in the list _lastThunkPtr = *((IntPtr*)_lastThunkPtr) + Constants.ThunkDataSize * (Constants.NumThunksPerBlock - 1); - InternalCalls.RhJitWriteProtect(1); - newBlockInfo._blockBaseAddress = thunkStubsBlock; newBlockInfo._nextBlock = _allocatedBlocks; @@ -224,10 +216,8 @@ public unsafe IntPtr AllocateThunk() Debug.Assert(nextAvailableThunkPtr != IntPtr.Zero); #if DEBUG - InternalCalls.RhJitWriteProtect(0); // Reset debug flag indicating the thunk is now in use *((IntPtr*)(nextAvailableThunkPtr + IntPtr.Size)) = IntPtr.Zero; - InternalCalls.RhJitWriteProtect(1); #endif int thunkIndex = (int)(((nuint)(nint)nextAvailableThunkPtr) - ((nuint)(nint)nextAvailableThunkPtr & ~Constants.PageSizeMask)); @@ -252,12 +242,8 @@ public unsafe void FreeThunk(IntPtr thunkAddress) if (!IsThunkInHeap(thunkAddress)) EH.FallbackFailFast(RhFailFastReason.InternalError, null); - InternalCalls.RhJitWriteProtect(0); - // Debug flag indicating the thunk is no longer used *((IntPtr*)(dataAddress + IntPtr.Size)) = new IntPtr(-1); -#else - InternalCalls.RhJitWriteProtect(0); #endif InternalCalls.RhpAcquireThunkPoolLock(); @@ -266,8 +252,6 @@ public unsafe void FreeThunk(IntPtr thunkAddress) _nextAvailableThunkPtr = dataAddress; InternalCalls.RhpReleaseThunkPoolLock(); - - InternalCalls.RhJitWriteProtect(1); } private bool IsThunkInHeap(IntPtr thunkAddress) @@ -329,14 +313,10 @@ public unsafe bool TryGetThunkData(IntPtr thunkAddress, out IntPtr context, out if (!IsThunkInHeap(thunkAddress)) return false; - InternalCalls.RhJitWriteProtect(0); - // Update the data that will be used by the thunk that was allocated context = *((IntPtr*)(dataAddress)); target = *((IntPtr*)(dataAddress + IntPtr.Size)); - InternalCalls.RhJitWriteProtect(1); - return true; } @@ -357,13 +337,9 @@ public unsafe void SetThunkData(IntPtr thunkAddress, IntPtr context, IntPtr targ EH.FallbackFailFast(RhFailFastReason.InternalError, null); #endif - InternalCalls.RhJitWriteProtect(0); - // Update the data that will be used by the thunk that was allocated *((IntPtr*)(dataAddress)) = context; *((IntPtr*)(dataAddress + IntPtr.Size)) = target; - - InternalCalls.RhJitWriteProtect(1); } } @@ -420,8 +396,6 @@ public static unsafe IntPtr GetNewThunksBlock() // Use the first data field of the thunk to build the linked list. IntPtr dataAddress = InternalCalls.RhpGetThunkDataBlockAddress(nextThunksBlock); - InternalCalls.RhJitWriteProtect(0); - for (int i = 0; i < Constants.NumThunksPerBlock; i++) { if (i == (Constants.NumThunksPerBlock - 1)) @@ -437,8 +411,6 @@ public static unsafe IntPtr GetNewThunksBlock() dataAddress += Constants.ThunkDataSize; } - InternalCalls.RhJitWriteProtect(1); - return nextThunksBlock; } diff --git a/src/coreclr/nativeaot/Runtime/ThunksMapping.cpp b/src/coreclr/nativeaot/Runtime/ThunksMapping.cpp index c2a74a6c7a0d0e..f540d62b2e980d 100644 --- a/src/coreclr/nativeaot/Runtime/ThunksMapping.cpp +++ b/src/coreclr/nativeaot/Runtime/ThunksMapping.cpp @@ -89,13 +89,6 @@ COOP_PINVOKE_HELPER(int, RhpGetThunkBlockSize, ()) return OS_PAGE_SIZE; } -EXTERN_C NATIVEAOT_API void __cdecl RhJitWriteProtect(int writeEnable) -{ -#if defined(HOST_OSX) && defined(HOST_ARM64) - pthread_jit_write_protect_np(writeEnable); -#endif -} - EXTERN_C NATIVEAOT_API void* __cdecl RhAllocateThunksMapping() { #ifdef WIN32 @@ -128,8 +121,9 @@ EXTERN_C NATIVEAOT_API void* __cdecl RhAllocateThunksMapping() return NULL; } - RhJitWriteProtect(0); - +#if defined(HOST_OSX) && defined(HOST_ARM64) + pthread_jit_write_protect_np(0); +#endif #endif int numBlocksPerMap = RhpGetNumThunkBlocksPerMapping(); @@ -233,7 +227,8 @@ EXTERN_C NATIVEAOT_API void* __cdecl RhAllocateThunksMapping() } #if defined(HOST_OSX) && defined(HOST_ARM64) - RhJitWriteProtect(1); + pthread_jit_write_protect_np(1); + __builtin___clear_cache((char*)pThunksSection, (char*)pThunksSection + THUNKS_MAP_SIZE); #else if (!PalVirtualProtect(pThunksSection, THUNKS_MAP_SIZE, PAGE_EXECUTE_READ)) { From b05ba08c2c1dd40c74aa449f1a45ea2cb9e6f7ae Mon Sep 17 00:00:00 2001 From: Filip Navara Date: Thu, 8 Sep 2022 00:28:42 +0200 Subject: [PATCH 07/19] Fix incorrect OS_PAGE_SIZE definition --- src/coreclr/nativeaot/Runtime/CommonMacros.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/coreclr/nativeaot/Runtime/CommonMacros.h b/src/coreclr/nativeaot/Runtime/CommonMacros.h index 5a74ff61c7372f..9a34ffd50ad8d8 100644 --- a/src/coreclr/nativeaot/Runtime/CommonMacros.h +++ b/src/coreclr/nativeaot/Runtime/CommonMacros.h @@ -155,8 +155,12 @@ inline bool IS_ALIGNED(T* val, uintptr_t alignment); #define DATA_ALIGNMENT 8 #ifndef OS_PAGE_SIZE +#if __APPLE__ +#define OS_PAGE_SIZE 0x4000 +#else #define OS_PAGE_SIZE 0x1000 #endif +#endif #elif defined(HOST_WASM) From 8742268ba44023435159531aee7fa0376df45860 Mon Sep 17 00:00:00 2001 From: Filip Navara Date: Thu, 8 Sep 2022 10:16:02 +0200 Subject: [PATCH 08/19] Fix TLS register trashing --- src/coreclr/nativeaot/Runtime/unix/unixasmmacrosarm64.inc | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/coreclr/nativeaot/Runtime/unix/unixasmmacrosarm64.inc b/src/coreclr/nativeaot/Runtime/unix/unixasmmacrosarm64.inc index 9284c7bbf4d757..cc6df7f2287a9e 100644 --- a/src/coreclr/nativeaot/Runtime/unix/unixasmmacrosarm64.inc +++ b/src/coreclr/nativeaot/Runtime/unix/unixasmmacrosarm64.inc @@ -182,6 +182,10 @@ C_FUNC(\Name): .endif stp x0, lr, [sp,#-0x10]! +#if defined(__APPLE__) + // Apple's tls_get_var trashes xip0 (and possibly xip1) + stp xip0, xip1, [sp,#-0x10]! +#endif // This sequence of instructions is recognized and potentially patched // by the linker (GD->IE/LE relaxation). @@ -206,6 +210,9 @@ C_FUNC(\Name): add \target, \target, x0 #endif +#if defined(__APPLE__) + ldp xip0, xip1, [sp],#0x10 +#endif ldp x0, lr, [sp],#0x10 .endm From 92a7164d5901f86093c5ff3a7cc2c0877251adec Mon Sep 17 00:00:00 2001 From: Filip Navara Date: Thu, 8 Sep 2022 12:35:25 +0200 Subject: [PATCH 09/19] Fix memory trashing caused by incorrect PREPARE_EXTERNAL_VAR_INDIRECT[_W] definitions --- src/coreclr/nativeaot/Runtime/unix/unixasmmacrosarm64.inc | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/coreclr/nativeaot/Runtime/unix/unixasmmacrosarm64.inc b/src/coreclr/nativeaot/Runtime/unix/unixasmmacrosarm64.inc index cc6df7f2287a9e..2323b9f24f8fb2 100644 --- a/src/coreclr/nativeaot/Runtime/unix/unixasmmacrosarm64.inc +++ b/src/coreclr/nativeaot/Runtime/unix/unixasmmacrosarm64.inc @@ -73,6 +73,7 @@ C_FUNC(\Name): #if defined(__APPLE__) adrp \HelperReg, C_FUNC(\Name)@GOTPAGE ldr \HelperReg, [\HelperReg, C_FUNC(\Name)@GOTPAGEOFF] + ldr \HelperReg, [\HelperReg] #else adrp \HelperReg, C_FUNC(\Name) ldr \HelperReg, [\HelperReg, :lo12:C_FUNC(\Name)] @@ -82,7 +83,8 @@ C_FUNC(\Name): .macro PREPARE_EXTERNAL_VAR_INDIRECT_W Name, HelperReg #if defined(__APPLE__) adrp x\HelperReg, C_FUNC(\Name)@GOTPAGE - ldr w\HelperReg, [x\HelperReg, C_FUNC(\Name)@GOTPAGEOFF] + ldr x\HelperReg, [x\HelperReg, C_FUNC(\Name)@GOTPAGEOFF] + ldr w\HelperReg, [x\HelperReg] #else adrp x\HelperReg, C_FUNC(\Name) ldr w\HelperReg, [x\HelperReg, :lo12:C_FUNC(\Name)] From 6325ba77e19d5b4e210241ce1dc7138a3472e95c Mon Sep 17 00:00:00 2001 From: Filip Navara Date: Thu, 8 Sep 2022 14:32:31 +0200 Subject: [PATCH 10/19] Ignore ESRCH in PalHijack (thread is already gone) --- src/coreclr/nativeaot/Runtime/unix/PalRedhawkUnix.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/coreclr/nativeaot/Runtime/unix/PalRedhawkUnix.cpp b/src/coreclr/nativeaot/Runtime/unix/PalRedhawkUnix.cpp index 7a49115ae413d2..dcdab47e46ec44 100644 --- a/src/coreclr/nativeaot/Runtime/unix/PalRedhawkUnix.cpp +++ b/src/coreclr/nativeaot/Runtime/unix/PalRedhawkUnix.cpp @@ -1064,7 +1064,7 @@ REDHAWK_PALEXPORT void REDHAWK_PALAPI PalHijack(HANDLE hThread, _In_opt_ void* p } #endif - if ((status != 0) && (status != EAGAIN)) + if ((status != 0) && (status != EAGAIN) && (status != ESRCH)) { // Failure to send the signal is fatal. There are only two cases when sending // the signal can fail. First, if the signal ID is invalid and second, From 125bed795af184f80a4018d063cfbe29e3b6a597 Mon Sep 17 00:00:00 2001 From: Filip Navara Date: Thu, 8 Sep 2022 16:13:03 +0200 Subject: [PATCH 11/19] Make CompactUnwinder_* parametrized with registry class --- .../llvm-libunwind/src/CompactUnwinder.hpp | 112 +++++++++--------- 1 file changed, 56 insertions(+), 56 deletions(-) diff --git a/src/native/external/llvm-libunwind/src/CompactUnwinder.hpp b/src/native/external/llvm-libunwind/src/CompactUnwinder.hpp index 41ec272e1e4fba..95456b067f9fd3 100644 --- a/src/native/external/llvm-libunwind/src/CompactUnwinder.hpp +++ b/src/native/external/llvm-libunwind/src/CompactUnwinder.hpp @@ -28,34 +28,34 @@ namespace libunwind { #if defined(_LIBUNWIND_TARGET_I386) /// CompactUnwinder_x86 uses a compact unwind info to virtually "step" (aka /// unwind) by modifying a Registers_x86 register set -template +template class CompactUnwinder_x86 { public: static int stepWithCompactEncoding(compact_unwind_encoding_t info, uint32_t functionStart, A &addressSpace, - Registers_x86 ®isters); + R ®isters); private: typename A::pint_t pint_t; - static void frameUnwind(A &addressSpace, Registers_x86 ®isters); + static void frameUnwind(A &addressSpace, R ®isters); static void framelessUnwind(A &addressSpace, typename A::pint_t returnAddressLocation, - Registers_x86 ®isters); + R ®isters); static int stepWithCompactEncodingEBPFrame(compact_unwind_encoding_t compactEncoding, uint32_t functionStart, A &addressSpace, - Registers_x86 ®isters); + R ®isters); static int stepWithCompactEncodingFrameless( compact_unwind_encoding_t compactEncoding, uint32_t functionStart, - A &addressSpace, Registers_x86 ®isters, bool indirectStackSize); + A &addressSpace, R ®isters, bool indirectStackSize); }; -template -int CompactUnwinder_x86::stepWithCompactEncoding( +template +int CompactUnwinder_x86::stepWithCompactEncoding( compact_unwind_encoding_t compactEncoding, uint32_t functionStart, - A &addressSpace, Registers_x86 ®isters) { + A &addressSpace, R ®isters) { switch (compactEncoding & UNWIND_X86_MODE_MASK) { case UNWIND_X86_MODE_EBP_FRAME: return stepWithCompactEncodingEBPFrame(compactEncoding, functionStart, @@ -70,10 +70,10 @@ int CompactUnwinder_x86::stepWithCompactEncoding( _LIBUNWIND_ABORT("invalid compact unwind encoding"); } -template -int CompactUnwinder_x86::stepWithCompactEncodingEBPFrame( +template +int CompactUnwinder_x86::stepWithCompactEncodingEBPFrame( compact_unwind_encoding_t compactEncoding, uint32_t functionStart, - A &addressSpace, Registers_x86 ®isters) { + A &addressSpace, R ®isters) { uint32_t savedRegistersOffset = EXTRACT_BITS(compactEncoding, UNWIND_X86_EBP_FRAME_OFFSET); uint32_t savedRegistersLocations = @@ -114,10 +114,10 @@ int CompactUnwinder_x86::stepWithCompactEncodingEBPFrame( return UNW_STEP_SUCCESS; } -template -int CompactUnwinder_x86::stepWithCompactEncodingFrameless( +template +int CompactUnwinder_x86::stepWithCompactEncodingFrameless( compact_unwind_encoding_t encoding, uint32_t functionStart, - A &addressSpace, Registers_x86 ®isters, bool indirectStackSize) { + A &addressSpace, R ®isters, bool indirectStackSize) { uint32_t stackSizeEncoded = EXTRACT_BITS(encoding, UNWIND_X86_FRAMELESS_STACK_SIZE); uint32_t stackAdjust = @@ -233,9 +233,9 @@ int CompactUnwinder_x86::stepWithCompactEncodingFrameless( } -template -void CompactUnwinder_x86::frameUnwind(A &addressSpace, - Registers_x86 ®isters) { +template +void CompactUnwinder_x86::frameUnwind(A &addressSpace, + R ®isters) { typename A::pint_t bp = registers.getEBP(); // ebp points to old ebp registers.setEBP(addressSpace.get32(bp), bp); @@ -245,10 +245,10 @@ void CompactUnwinder_x86::frameUnwind(A &addressSpace, registers.setIP(addressSpace.get32(bp + 4), bp + 4); } -template -void CompactUnwinder_x86::framelessUnwind( +template +void CompactUnwinder_x86::framelessUnwind( A &addressSpace, typename A::pint_t returnAddressLocation, - Registers_x86 ®isters) { + R ®isters) { // return address is on stack after last saved register registers.setIP(addressSpace.get32(returnAddressLocation), returnAddressLocation); // old esp is before return address @@ -260,33 +260,33 @@ void CompactUnwinder_x86::framelessUnwind( #if defined(_LIBUNWIND_TARGET_X86_64) /// CompactUnwinder_x86_64 uses a compact unwind info to virtually "step" (aka /// unwind) by modifying a Registers_x86_64 register set -template +template class CompactUnwinder_x86_64 { public: static int stepWithCompactEncoding(compact_unwind_encoding_t compactEncoding, uint64_t functionStart, A &addressSpace, - Registers_x86_64 ®isters); + R ®isters); private: typename A::pint_t pint_t; - static void frameUnwind(A &addressSpace, Registers_x86_64 ®isters); + static void frameUnwind(A &addressSpace, R ®isters); static void framelessUnwind(A &addressSpace, uint64_t returnAddressLocation, - Registers_x86_64 ®isters); + R ®isters); static int stepWithCompactEncodingRBPFrame(compact_unwind_encoding_t compactEncoding, uint64_t functionStart, A &addressSpace, - Registers_x86_64 ®isters); + R ®isters); static int stepWithCompactEncodingFrameless( compact_unwind_encoding_t compactEncoding, uint64_t functionStart, - A &addressSpace, Registers_x86_64 ®isters, bool indirectStackSize); + A &addressSpace, R ®isters, bool indirectStackSize); }; -template -int CompactUnwinder_x86_64::stepWithCompactEncoding( +template +int CompactUnwinder_x86_64::stepWithCompactEncoding( compact_unwind_encoding_t compactEncoding, uint64_t functionStart, - A &addressSpace, Registers_x86_64 ®isters) { + A &addressSpace, R ®isters) { switch (compactEncoding & UNWIND_X86_64_MODE_MASK) { case UNWIND_X86_64_MODE_RBP_FRAME: return stepWithCompactEncodingRBPFrame(compactEncoding, functionStart, @@ -301,10 +301,10 @@ int CompactUnwinder_x86_64::stepWithCompactEncoding( _LIBUNWIND_ABORT("invalid compact unwind encoding"); } -template -int CompactUnwinder_x86_64::stepWithCompactEncodingRBPFrame( +template +int CompactUnwinder_x86_64::stepWithCompactEncodingRBPFrame( compact_unwind_encoding_t compactEncoding, uint64_t functionStart, - A &addressSpace, Registers_x86_64 ®isters) { + A &addressSpace, R ®isters) { uint32_t savedRegistersOffset = EXTRACT_BITS(compactEncoding, UNWIND_X86_64_RBP_FRAME_OFFSET); uint32_t savedRegistersLocations = @@ -345,10 +345,10 @@ int CompactUnwinder_x86_64::stepWithCompactEncodingRBPFrame( return UNW_STEP_SUCCESS; } -template -int CompactUnwinder_x86_64::stepWithCompactEncodingFrameless( +template +int CompactUnwinder_x86_64::stepWithCompactEncodingFrameless( compact_unwind_encoding_t encoding, uint64_t functionStart, A &addressSpace, - Registers_x86_64 ®isters, bool indirectStackSize) { + R ®isters, bool indirectStackSize) { uint32_t stackSizeEncoded = EXTRACT_BITS(encoding, UNWIND_X86_64_FRAMELESS_STACK_SIZE); uint32_t stackAdjust = @@ -464,9 +464,9 @@ int CompactUnwinder_x86_64::stepWithCompactEncodingFrameless( } -template -void CompactUnwinder_x86_64::frameUnwind(A &addressSpace, - Registers_x86_64 ®isters) { +template +void CompactUnwinder_x86_64::frameUnwind(A &addressSpace, + R ®isters) { uint64_t rbp = registers.getRBP(); // ebp points to old ebp registers.setRBP(addressSpace.get64(rbp), rbp); @@ -476,10 +476,10 @@ void CompactUnwinder_x86_64::frameUnwind(A &addressSpace, registers.setIP(addressSpace.get64(rbp + 8), rbp + 8); } -template -void CompactUnwinder_x86_64::framelessUnwind(A &addressSpace, - uint64_t returnAddressLocation, - Registers_x86_64 ®isters) { +template +void CompactUnwinder_x86_64::framelessUnwind(A &addressSpace, + uint64_t returnAddressLocation, + R ®isters) { // return address is on stack after last saved register registers.setIP(addressSpace.get64(returnAddressLocation), returnAddressLocation); // old esp is before return address @@ -492,13 +492,13 @@ void CompactUnwinder_x86_64::framelessUnwind(A &addressSpace, #if defined(_LIBUNWIND_TARGET_AARCH64) /// CompactUnwinder_arm64 uses a compact unwind info to virtually "step" (aka /// unwind) by modifying a Registers_arm64 register set -template +template class CompactUnwinder_arm64 { public: static int stepWithCompactEncoding(compact_unwind_encoding_t compactEncoding, uint64_t functionStart, A &addressSpace, - Registers_arm64 ®isters); + R ®isters); private: typename A::pint_t pint_t; @@ -506,16 +506,16 @@ class CompactUnwinder_arm64 { static int stepWithCompactEncodingFrame(compact_unwind_encoding_t compactEncoding, uint64_t functionStart, A &addressSpace, - Registers_arm64 ®isters); + R ®isters); static int stepWithCompactEncodingFrameless( compact_unwind_encoding_t compactEncoding, uint64_t functionStart, - A &addressSpace, Registers_arm64 ®isters); + A &addressSpace, R ®isters); }; -template -int CompactUnwinder_arm64::stepWithCompactEncoding( +template +int CompactUnwinder_arm64::stepWithCompactEncoding( compact_unwind_encoding_t compactEncoding, uint64_t functionStart, - A &addressSpace, Registers_arm64 ®isters) { + A &addressSpace, R ®isters) { switch (compactEncoding & UNWIND_ARM64_MODE_MASK) { case UNWIND_ARM64_MODE_FRAME: return stepWithCompactEncodingFrame(compactEncoding, functionStart, @@ -527,10 +527,10 @@ int CompactUnwinder_arm64::stepWithCompactEncoding( _LIBUNWIND_ABORT("invalid compact unwind encoding"); } -template -int CompactUnwinder_arm64::stepWithCompactEncodingFrameless( +template +int CompactUnwinder_arm64::stepWithCompactEncodingFrameless( compact_unwind_encoding_t encoding, uint64_t, A &addressSpace, - Registers_arm64 ®isters) { + R ®isters) { uint32_t stackSize = 16 * EXTRACT_BITS(encoding, UNWIND_ARM64_FRAMELESS_STACK_SIZE_MASK); @@ -609,10 +609,10 @@ int CompactUnwinder_arm64::stepWithCompactEncodingFrameless( return UNW_STEP_SUCCESS; } -template -int CompactUnwinder_arm64::stepWithCompactEncodingFrame( +template +int CompactUnwinder_arm64::stepWithCompactEncodingFrame( compact_unwind_encoding_t encoding, uint64_t, A &addressSpace, - Registers_arm64 ®isters) { + R ®isters) { uint64_t savedRegisterLoc = registers.getFP() - 8; if (encoding & UNWIND_ARM64_FRAME_X19_X20_PAIR) { From 817b10cea5cb957724eba59c93c71b13b485437a Mon Sep 17 00:00:00 2001 From: Filip Navara Date: Thu, 8 Sep 2022 16:13:36 +0200 Subject: [PATCH 12/19] Remove custom CompactUnwinder --- .../nativeaot/Runtime/unix/UnwindHelpers.cpp | 216 ++---------------- 1 file changed, 14 insertions(+), 202 deletions(-) diff --git a/src/coreclr/nativeaot/Runtime/unix/UnwindHelpers.cpp b/src/coreclr/nativeaot/Runtime/unix/UnwindHelpers.cpp index 72f448ed76e999..b81e5aa0625988 100644 --- a/src/coreclr/nativeaot/Runtime/unix/UnwindHelpers.cpp +++ b/src/coreclr/nativeaot/Runtime/unix/UnwindHelpers.cpp @@ -28,10 +28,12 @@ #if defined(TARGET_AMD64) using libunwind::Registers_x86_64; +using libunwind::CompactUnwinder_x86_64; #elif defined(TARGET_ARM) using libunwind::Registers_arm; #elif defined(TARGET_ARM64) using libunwind::Registers_arm64; +using libunwind::CompactUnwinder_arm64; #elif defined(TARGET_X86) using libunwind::Registers_x86; #else @@ -501,6 +503,8 @@ struct Registers_REGDISPLAY : REGDISPLAY uint64_t getIP() const { return IP;} void setIP(uint64_t value, uint64_t location) { IP = value; pIP = (PTR_UIntNative)location; } + uint64_t getFP() const { return *pFP;} + void setFP(uint64_t value, uint64_t location) { pFP = (PTR_UIntNative)location;} }; inline bool Registers_REGDISPLAY::validRegister(int num) const { @@ -755,206 +759,6 @@ void Registers_REGDISPLAY::setVectorRegister(int num, libunwind::v128 value) D[num] = (uint64_t)value.vec[2] << 32 | (uint64_t)value.vec[3]; } -/// CompactUnwinder_arm64 uses a compact unwind info to virtually "step" (aka -/// unwind) by modifying a Registers_arm64 register set -template -class CompactUnwinder_arm64 { -public: - - static int stepWithCompactEncoding(compact_unwind_encoding_t compactEncoding, - uint64_t functionStart, A &addressSpace, - Registers_REGDISPLAY ®isters); - -private: - typename A::pint_t pint_t; - - static int - stepWithCompactEncodingFrame(compact_unwind_encoding_t compactEncoding, - uint64_t functionStart, A &addressSpace, - Registers_REGDISPLAY ®isters); - static int stepWithCompactEncodingFrameless( - compact_unwind_encoding_t compactEncoding, uint64_t functionStart, - A &addressSpace, Registers_REGDISPLAY ®isters); -}; - -template -int CompactUnwinder_arm64::stepWithCompactEncoding( - compact_unwind_encoding_t compactEncoding, uint64_t functionStart, - A &addressSpace, Registers_REGDISPLAY ®isters) { - switch (compactEncoding & UNWIND_ARM64_MODE_MASK) { - case UNWIND_ARM64_MODE_FRAME: - return stepWithCompactEncodingFrame(compactEncoding, functionStart, - addressSpace, registers); - case UNWIND_ARM64_MODE_FRAMELESS: - return stepWithCompactEncodingFrameless(compactEncoding, functionStart, - addressSpace, registers); - } - _LIBUNWIND_ABORT("invalid compact unwind encoding"); -} - -template -int CompactUnwinder_arm64::stepWithCompactEncodingFrameless( - compact_unwind_encoding_t encoding, uint64_t, A &addressSpace, - Registers_REGDISPLAY ®isters) { - uint32_t stackSize = - 16 * EXTRACT_BITS(encoding, UNWIND_ARM64_FRAMELESS_STACK_SIZE_MASK); - - uint64_t savedRegisterLoc = registers.getSP() + stackSize; - - if (encoding & UNWIND_ARM64_FRAME_X19_X20_PAIR) { - registers.setRegister(UNW_AARCH64_X19, addressSpace.get64(savedRegisterLoc), savedRegisterLoc); - savedRegisterLoc -= 8; - registers.setRegister(UNW_AARCH64_X20, addressSpace.get64(savedRegisterLoc), savedRegisterLoc); - savedRegisterLoc -= 8; - } - if (encoding & UNWIND_ARM64_FRAME_X21_X22_PAIR) { - registers.setRegister(UNW_AARCH64_X21, addressSpace.get64(savedRegisterLoc), savedRegisterLoc); - savedRegisterLoc -= 8; - registers.setRegister(UNW_AARCH64_X22, addressSpace.get64(savedRegisterLoc), savedRegisterLoc); - savedRegisterLoc -= 8; - } - if (encoding & UNWIND_ARM64_FRAME_X23_X24_PAIR) { - registers.setRegister(UNW_AARCH64_X23, addressSpace.get64(savedRegisterLoc), savedRegisterLoc); - savedRegisterLoc -= 8; - registers.setRegister(UNW_AARCH64_X24, addressSpace.get64(savedRegisterLoc), savedRegisterLoc); - savedRegisterLoc -= 8; - } - if (encoding & UNWIND_ARM64_FRAME_X25_X26_PAIR) { - registers.setRegister(UNW_AARCH64_X25, addressSpace.get64(savedRegisterLoc), savedRegisterLoc); - savedRegisterLoc -= 8; - registers.setRegister(UNW_AARCH64_X26, addressSpace.get64(savedRegisterLoc), savedRegisterLoc); - savedRegisterLoc -= 8; - } - if (encoding & UNWIND_ARM64_FRAME_X27_X28_PAIR) { - registers.setRegister(UNW_AARCH64_X27, addressSpace.get64(savedRegisterLoc), savedRegisterLoc); - savedRegisterLoc -= 8; - registers.setRegister(UNW_AARCH64_X28, addressSpace.get64(savedRegisterLoc), savedRegisterLoc); - savedRegisterLoc -= 8; - } - - if (encoding & UNWIND_ARM64_FRAME_D8_D9_PAIR) { - registers.setFloatRegister(UNW_AARCH64_V8, - addressSpace.getDouble(savedRegisterLoc)); - savedRegisterLoc -= 8; - registers.setFloatRegister(UNW_AARCH64_V9, - addressSpace.getDouble(savedRegisterLoc)); - savedRegisterLoc -= 8; - } - if (encoding & UNWIND_ARM64_FRAME_D10_D11_PAIR) { - registers.setFloatRegister(UNW_AARCH64_V10, - addressSpace.getDouble(savedRegisterLoc)); - savedRegisterLoc -= 8; - registers.setFloatRegister(UNW_AARCH64_V11, - addressSpace.getDouble(savedRegisterLoc)); - savedRegisterLoc -= 8; - } - if (encoding & UNWIND_ARM64_FRAME_D12_D13_PAIR) { - registers.setFloatRegister(UNW_AARCH64_V12, - addressSpace.getDouble(savedRegisterLoc)); - savedRegisterLoc -= 8; - registers.setFloatRegister(UNW_AARCH64_V13, - addressSpace.getDouble(savedRegisterLoc)); - savedRegisterLoc -= 8; - } - if (encoding & UNWIND_ARM64_FRAME_D14_D15_PAIR) { - registers.setFloatRegister(UNW_AARCH64_V14, - addressSpace.getDouble(savedRegisterLoc)); - savedRegisterLoc -= 8; - registers.setFloatRegister(UNW_AARCH64_V15, - addressSpace.getDouble(savedRegisterLoc)); - savedRegisterLoc -= 8; - } - - // subtract stack size off of sp - registers.setSP(savedRegisterLoc, 0); - - // set pc to be value in lr - registers.setIP(registers.getRegister(UNW_AARCH64_LR), 0); - - return UNW_STEP_SUCCESS; -} - -template -int CompactUnwinder_arm64::stepWithCompactEncodingFrame( - compact_unwind_encoding_t encoding, uint64_t, A &addressSpace, - Registers_REGDISPLAY ®isters) { - uint64_t savedRegisterLoc = registers.GetFP() - 8; - - if (encoding & UNWIND_ARM64_FRAME_X19_X20_PAIR) { - registers.setRegister(UNW_AARCH64_X19, addressSpace.get64(savedRegisterLoc), savedRegisterLoc); - savedRegisterLoc -= 8; - registers.setRegister(UNW_AARCH64_X20, addressSpace.get64(savedRegisterLoc), savedRegisterLoc); - savedRegisterLoc -= 8; - } - if (encoding & UNWIND_ARM64_FRAME_X21_X22_PAIR) { - registers.setRegister(UNW_AARCH64_X21, addressSpace.get64(savedRegisterLoc), savedRegisterLoc); - savedRegisterLoc -= 8; - registers.setRegister(UNW_AARCH64_X22, addressSpace.get64(savedRegisterLoc), savedRegisterLoc); - savedRegisterLoc -= 8; - } - if (encoding & UNWIND_ARM64_FRAME_X23_X24_PAIR) { - registers.setRegister(UNW_AARCH64_X23, addressSpace.get64(savedRegisterLoc), savedRegisterLoc); - savedRegisterLoc -= 8; - registers.setRegister(UNW_AARCH64_X24, addressSpace.get64(savedRegisterLoc), savedRegisterLoc); - savedRegisterLoc -= 8; - } - if (encoding & UNWIND_ARM64_FRAME_X25_X26_PAIR) { - registers.setRegister(UNW_AARCH64_X25, addressSpace.get64(savedRegisterLoc), savedRegisterLoc); - savedRegisterLoc -= 8; - registers.setRegister(UNW_AARCH64_X26, addressSpace.get64(savedRegisterLoc), savedRegisterLoc); - savedRegisterLoc -= 8; - } - if (encoding & UNWIND_ARM64_FRAME_X27_X28_PAIR) { - registers.setRegister(UNW_AARCH64_X27, addressSpace.get64(savedRegisterLoc), savedRegisterLoc); - savedRegisterLoc -= 8; - registers.setRegister(UNW_AARCH64_X28, addressSpace.get64(savedRegisterLoc), savedRegisterLoc); - savedRegisterLoc -= 8; - } - - if (encoding & UNWIND_ARM64_FRAME_D8_D9_PAIR) { - registers.setFloatRegister(UNW_AARCH64_V8, - addressSpace.getDouble(savedRegisterLoc)); - savedRegisterLoc -= 8; - registers.setFloatRegister(UNW_AARCH64_V9, - addressSpace.getDouble(savedRegisterLoc)); - savedRegisterLoc -= 8; - } - if (encoding & UNWIND_ARM64_FRAME_D10_D11_PAIR) { - registers.setFloatRegister(UNW_AARCH64_V10, - addressSpace.getDouble(savedRegisterLoc)); - savedRegisterLoc -= 8; - registers.setFloatRegister(UNW_AARCH64_V11, - addressSpace.getDouble(savedRegisterLoc)); - savedRegisterLoc -= 8; - } - if (encoding & UNWIND_ARM64_FRAME_D12_D13_PAIR) { - registers.setFloatRegister(UNW_AARCH64_V12, - addressSpace.getDouble(savedRegisterLoc)); - savedRegisterLoc -= 8; - registers.setFloatRegister(UNW_AARCH64_V13, - addressSpace.getDouble(savedRegisterLoc)); - savedRegisterLoc -= 8; - } - if (encoding & UNWIND_ARM64_FRAME_D14_D15_PAIR) { - registers.setFloatRegister(UNW_AARCH64_V14, - addressSpace.getDouble(savedRegisterLoc)); - savedRegisterLoc -= 8; - registers.setFloatRegister(UNW_AARCH64_V15, - addressSpace.getDouble(savedRegisterLoc)); - savedRegisterLoc -= 8; - } - - uint64_t fp = registers.GetFP(); - // fp points to old fp - registers.setRegister(UNW_ARM64_FP, addressSpace.get64(fp), fp); - // old sp is fp less saved fp and lr - registers.setSP(fp + 16, 0); - // pop return address into pc - registers.setIP(addressSpace.get64(fp + 8), fp + 8); - - return UNW_STEP_SUCCESS; -} - #endif // TARGET_ARM64 bool DoTheStep(uintptr_t pc, UnwindInfoSections uwInfoSections, REGDISPLAY *regs) @@ -980,9 +784,17 @@ bool DoTheStep(uintptr_t pc, UnwindInfoSections uwInfoSections, REGDISPLAY *regs unw_proc_info_t procInfo; uc.getInfo(&procInfo); -#if defined(_LIBUNWIND_TARGET_AARCH64) +#if defined(TARGET_ARM64) if ((procInfo.format & UNWIND_ARM64_MODE_MASK) != UNWIND_ARM64_MODE_DWARF) { - CompactUnwinder_arm64 compactInst; + CompactUnwinder_arm64 compactInst; + int stepRet = compactInst.stepWithCompactEncoding(procInfo.format, pc, _addressSpace, *(Registers_REGDISPLAY*)regs); + return stepRet == UNW_STEP_SUCCESS; + } else { + dwarfOffsetHint = procInfo.format & UNWIND_ARM64_DWARF_SECTION_OFFSET; + } +#elif defined(TARGET_AMD64) + if ((procInfo.format & UNWIND_X86_64_MODE_MASK) != UNWIND_X86_64_MODE_DWARF) { + CompactUnwinder_x86_64 compactInst; int stepRet = compactInst.stepWithCompactEncoding(procInfo.format, pc, _addressSpace, *(Registers_REGDISPLAY*)regs); return stepRet == UNW_STEP_SUCCESS; } else { From f44843f8660cb59be9236b1ebe2349a8091a7ed3 Mon Sep 17 00:00:00 2001 From: Filip Navara Date: Thu, 8 Sep 2022 16:14:06 +0200 Subject: [PATCH 13/19] Update src/coreclr/nativeaot/Runtime/CommonMacros.h Co-authored-by: Adeel Mujahid <3840695+am11@users.noreply.github.com> --- src/coreclr/nativeaot/Runtime/CommonMacros.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/coreclr/nativeaot/Runtime/CommonMacros.h b/src/coreclr/nativeaot/Runtime/CommonMacros.h index 9a34ffd50ad8d8..dba787f1ad5454 100644 --- a/src/coreclr/nativeaot/Runtime/CommonMacros.h +++ b/src/coreclr/nativeaot/Runtime/CommonMacros.h @@ -155,7 +155,7 @@ inline bool IS_ALIGNED(T* val, uintptr_t alignment); #define DATA_ALIGNMENT 8 #ifndef OS_PAGE_SIZE -#if __APPLE__ +#ifdef HOST_OSX #define OS_PAGE_SIZE 0x4000 #else #define OS_PAGE_SIZE 0x1000 From 330849309aa4db04a061ee8709e98f7516142e18 Mon Sep 17 00:00:00 2001 From: Filip Navara Date: Thu, 8 Sep 2022 20:57:16 +0200 Subject: [PATCH 14/19] Update llvm-libunwind-version.txt --- src/native/external/llvm-libunwind-version.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/native/external/llvm-libunwind-version.txt b/src/native/external/llvm-libunwind-version.txt index 0a2c1f4f2f4007..3f5f8b71918963 100644 --- a/src/native/external/llvm-libunwind-version.txt +++ b/src/native/external/llvm-libunwind-version.txt @@ -3,3 +3,5 @@ https://github.com/llvm/llvm-project/releases/tag/llvmorg-14.0.6 Apply https://github.com/dotnet/runtime/commit/e57194552327bccaf2b45a9190f0e6e1289472e4 Apply https://github.com/dotnet/runtime/commit/db7ed089a9e20a391a53e0b547f95dc8bf916765 +Apply https://github.com/dotnet/runtime/commit/828c8d0b2a8cdc2479524c5229939641d3610a1b +Apply https://github.com/dotnet/runtime/commit/92e7dffffbcd9725616741fbd73a7e7e1f5e97a4 \ No newline at end of file From 8b9d0dc5e728249039080a1a290966243635877e Mon Sep 17 00:00:00 2001 From: Filip Navara Date: Fri, 9 Sep 2022 12:19:47 +0200 Subject: [PATCH 15/19] Fix initial alignment for __module_initializer. ARM64 requires absolute symbol relocations to be aligned to native pointer size. --- .../Compiler/DependencyAnalysis/ModuleInitializerListNode.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ModuleInitializerListNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ModuleInitializerListNode.cs index a88d3893e6697d..034e173083ed55 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ModuleInitializerListNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ModuleInitializerListNode.cs @@ -135,6 +135,7 @@ public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false) // the time of startup. (Linker likely can't do it, unfortunately.) ObjectDataBuilder builder = new ObjectDataBuilder(factory, relocsOnly); + builder.RequireInitialAlignment(factory.Target.PointerSize); builder.AddSymbol(this); builder.AddSymbol(_endSymbol); From 9d73bfaafca36d7c0b3a02e434f344f3a252b2ba Mon Sep 17 00:00:00 2001 From: Filip Navara Date: Fri, 9 Sep 2022 12:20:20 +0200 Subject: [PATCH 16/19] Allow publishing with the osx-arm64 RID --- .../BuildIntegration/Microsoft.NETCore.Native.Publish.targets | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/coreclr/nativeaot/BuildIntegration/Microsoft.NETCore.Native.Publish.targets b/src/coreclr/nativeaot/BuildIntegration/Microsoft.NETCore.Native.Publish.targets index 31fd3e65e351ea..cbed76ebd4142f 100644 --- a/src/coreclr/nativeaot/BuildIntegration/Microsoft.NETCore.Native.Publish.targets +++ b/src/coreclr/nativeaot/BuildIntegration/Microsoft.NETCore.Native.Publish.targets @@ -61,8 +61,7 @@ - Date: Fri, 9 Sep 2022 14:02:09 +0200 Subject: [PATCH 17/19] Use pointer sized alignment for fat function pointers since they contain absolute relocations. ld64 seem to silently corrupt them if they are not aligned to pointer size. --- .../Compiler/DependencyAnalysis/FatFunctionPointerNode.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/FatFunctionPointerNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/FatFunctionPointerNode.cs index a4622553d4c9ed..4e7396e8ff609e 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/FatFunctionPointerNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/FatFunctionPointerNode.cs @@ -60,8 +60,9 @@ public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false) { var builder = new ObjectDataBuilder(factory, relocsOnly); - // These need to be aligned the same as methods because they show up in same contexts - builder.RequireInitialAlignment(factory.Target.MinimumFunctionAlignment); + // These need to be aligned the same as method pointers because they show up in same contexts + // (macOS ARM64 has even stricter alignment requirement for the linker, so round up to pointer size) + builder.RequireInitialAlignment(factory.Target.PointerSize); builder.AddSymbol(this); From 59b79b3c07a0e36fb7a3ded9edf023a7c65fbeac Mon Sep 17 00:00:00 2001 From: Filip Navara Date: Sun, 11 Sep 2022 09:01:37 +0200 Subject: [PATCH 18/19] Remove __builtin___clear_cache, it was already fixed --- src/coreclr/nativeaot/Runtime/ThunksMapping.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/coreclr/nativeaot/Runtime/ThunksMapping.cpp b/src/coreclr/nativeaot/Runtime/ThunksMapping.cpp index f540d62b2e980d..d105f79506aca2 100644 --- a/src/coreclr/nativeaot/Runtime/ThunksMapping.cpp +++ b/src/coreclr/nativeaot/Runtime/ThunksMapping.cpp @@ -228,7 +228,6 @@ EXTERN_C NATIVEAOT_API void* __cdecl RhAllocateThunksMapping() #if defined(HOST_OSX) && defined(HOST_ARM64) pthread_jit_write_protect_np(1); - __builtin___clear_cache((char*)pThunksSection, (char*)pThunksSection + THUNKS_MAP_SIZE); #else if (!PalVirtualProtect(pThunksSection, THUNKS_MAP_SIZE, PAGE_EXECUTE_READ)) { From d8c7ee01ed195d0f7c7b445784e146ec1cfa26df Mon Sep 17 00:00:00 2001 From: Jan Kotas Date: Sun, 11 Sep 2022 08:16:11 -0700 Subject: [PATCH 19/19] Update src/coreclr/nativeaot/Runtime/unix/PalRedhawkUnix.cpp --- src/coreclr/nativeaot/Runtime/unix/PalRedhawkUnix.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/coreclr/nativeaot/Runtime/unix/PalRedhawkUnix.cpp b/src/coreclr/nativeaot/Runtime/unix/PalRedhawkUnix.cpp index dcdab47e46ec44..bcdbe419d2e07b 100644 --- a/src/coreclr/nativeaot/Runtime/unix/PalRedhawkUnix.cpp +++ b/src/coreclr/nativeaot/Runtime/unix/PalRedhawkUnix.cpp @@ -779,7 +779,8 @@ REDHAWK_PALEXPORT _Ret_maybenull_ _Post_writable_byte_size_(size) void* REDHAWK_ int flags = MAP_ANON | MAP_PRIVATE; #if defined(HOST_OSX) && defined(HOST_ARM64) - if (unixProtect & PROT_EXEC) { + if (unixProtect & PROT_EXEC) + { flags |= MAP_JIT; } #endif