diff --git a/src/coreclr/nativeaot/Runtime/Full/CMakeLists.txt b/src/coreclr/nativeaot/Runtime/Full/CMakeLists.txt index f9b390e18d117a..a7612de58d43d7 100644 --- a/src/coreclr/nativeaot/Runtime/Full/CMakeLists.txt +++ b/src/coreclr/nativeaot/Runtime/Full/CMakeLists.txt @@ -6,7 +6,7 @@ project(Runtime) # Include auto-generated files on include path set(CMAKE_INCLUDE_CURRENT_DIR ON) -if (CLR_CMAKE_TARGET_APPLE) +if (CLR_CMAKE_TARGET_APPLE OR CLR_CMAKE_TARGET_LINUX_MUSL) list(APPEND RUNTIME_SOURCES_ARCH_ASM ${ARCH_SOURCES_DIR}/ThunkPoolThunks.${ASM_SUFFIX} ) diff --git a/src/coreclr/nativeaot/Runtime/ThunksMapping.cpp b/src/coreclr/nativeaot/Runtime/ThunksMapping.cpp index c8f91a07a2819f..567284ff614e77 100644 --- a/src/coreclr/nativeaot/Runtime/ThunksMapping.cpp +++ b/src/coreclr/nativeaot/Runtime/ThunksMapping.cpp @@ -359,7 +359,7 @@ EXTERN_C void* QCALLTYPE RhAllocateThunksMapping() int thunkBlockSize = RhpGetThunkBlockSize(); int templateSize = thunkBlocksPerMapping * thunkBlockSize; -#ifndef TARGET_APPLE // Apple platforms cannot use the initial template +#ifndef TARGET_APPLE || TARGET_LINUX // Apple platforms cannot use the initial template if (pThunksTemplateAddress == NULL) { // First, we use the thunks directly from the thunks template sections in the module until all @@ -377,8 +377,9 @@ EXTERN_C void* QCALLTYPE RhAllocateThunksMapping() uint8_t* pModuleBase = (uint8_t*)PalGetModuleHandleFromPointer(RhpGetThunksBase()); int templateRva = (int)((uint8_t*)RhpGetThunksBase() - pModuleBase); - if (!PalAllocateThunksFromTemplate((HANDLE)pModuleBase, templateRva, templateSize, &pThunkMap)) + if (!PalAllocateThunksFromTemplate((HANDLE)pModuleBase, templateRva, templateSize, &pThunkMap)){ return NULL; + } } if (!PalMarkThunksAsValidCallTargets( diff --git a/src/coreclr/nativeaot/Runtime/arm64/ThunkPoolThunks.S b/src/coreclr/nativeaot/Runtime/arm64/ThunkPoolThunks.S index 1b0ea7e0291166..e9a7d74b47f8a4 100644 --- a/src/coreclr/nativeaot/Runtime/arm64/ThunkPoolThunks.S +++ b/src/coreclr/nativeaot/Runtime/arm64/ThunkPoolThunks.S @@ -12,17 +12,17 @@ #define THUNKS_MAP_SIZE 0x8000 -#ifdef TARGET_APPLE -#define PAGE_SIZE 0x4000 -#define PAGE_SIZE_LOG2 14 +#ifdef TARGET_LINUX +#define PAGE_SIZE 0x1000 +#define PAGE_SIZE_LOG2 12 #else #error Unsupported OS #endif // THUNK_POOL_NUM_THUNKS_PER_PAGE = min(PAGE_SIZE / THUNK_CODESIZE, (PAGE_SIZE - POINTER_SIZE) / THUNK_DATASIZE) -#define THUNK_POOL_NUM_THUNKS_PER_PAGE 0x3ff +#define THUNK_POOL_NUM_THUNKS_PER_PAGE 0xFF -//;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; Thunk Pages ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +#ifdef TARGET_LINUX .macro THUNKS_PAGE_BLOCK IN_PAGE_INDEX = 0 @@ -45,16 +45,17 @@ .endr .endm -#ifdef TARGET_APPLE // Thunk pool - .text + .section .thunks ,"ax" .p2align PAGE_SIZE_LOG2 PATCH_LABEL ThunkPool .rept (THUNKS_MAP_SIZE / PAGE_SIZE) .p2align PAGE_SIZE_LOG2 THUNKS_PAGE_BLOCK .endr + .space THUNKS_MAP_SIZE .p2align PAGE_SIZE_LOG2 + .section .text #else #error Unsupported OS #endif @@ -66,8 +67,8 @@ PATCH_LABEL ThunkPool // LEAF_ENTRY RhpGetThunksBase // Return the address of the first thunk pool to the caller (this is really the base address) - adrp x0, C_FUNC(ThunkPool)@PAGE - add x0, x0, C_FUNC(ThunkPool)@PAGEOFF + adrp x0, C_FUNC(ThunkPool) + add x0, x0, #:lo12:C_FUNC(ThunkPool) ret LEAF_END RhpGetThunksBase diff --git a/src/coreclr/nativeaot/Runtime/unix/PalRedhawkUnix.cpp b/src/coreclr/nativeaot/Runtime/unix/PalRedhawkUnix.cpp index d30c3cb3aa6af3..65e1fbd0c2bc5d 100644 --- a/src/coreclr/nativeaot/Runtime/unix/PalRedhawkUnix.cpp +++ b/src/coreclr/nativeaot/Runtime/unix/PalRedhawkUnix.cpp @@ -57,6 +57,11 @@ #ifdef TARGET_APPLE #include +#elif defined(TARGET_LINUX) +#include +#include +#include +#include #endif using std::nullptr_t; @@ -566,6 +571,45 @@ REDHAWK_PALEXPORT UInt32_BOOL REDHAWK_PALAPI PalAllocateThunksFromTemplate(HANDL *newThunksOut = (void*)addr; + return UInt32_TRUE; +#elif defined(TARGET_LINUX) + if (templateSize == 0) + { + return UInt32_FALSE; + } + + long pageSize = sysconf(_SC_PAGESIZE); + if (pageSize == -1) + { + return UInt32_FALSE; + } + + // Align templateSize to page boundary + size_t alignedSize = (templateSize + (size_t)pageSize - 1) & ~((size_t)pageSize - 1); + if (alignedSize > SIZE_MAX / 2) + { + return UInt32_FALSE; // Prevent overflow + } + + size_t totalSize = 2 * alignedSize; + void* allocation = mmap(NULL, totalSize, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + if (allocation == MAP_FAILED) + { + return UInt32_FALSE; + } + + // Copy template code to the first block + const void* templateSrc = (const void*)((uintptr_t)hTemplateModule + templateRva); + memcpy(allocation, templateSrc, templateSize); + __builtin___clear_cache((char*)allocation, (char*)allocation + templateSize); + // Set first block to RX permissions + if (mprotect(allocation, alignedSize, PROT_READ | PROT_EXEC) == -1) + { + munmap(allocation, totalSize); + return UInt32_FALSE; + } + __builtin___clear_cache((char*)allocation, (char*)allocation + templateSize); + *newThunksOut = allocation; return UInt32_TRUE; #else PORTABILITY_ASSERT("UNIXTODO: Implement this function"); @@ -583,6 +627,34 @@ REDHAWK_PALEXPORT UInt32_BOOL REDHAWK_PALAPI PalFreeThunksFromTemplate(void *pBa } while (ret == KERN_ABORTED); return ret == KERN_SUCCESS ? UInt32_TRUE : UInt32_FALSE; +#elif defined(TARGET_LINUX) + if (pBaseAddress == NULL || templateSize == 0) { + return UInt32_FALSE; + } + + // 获取系统页面大小 + long pageSize = sysconf(_SC_PAGESIZE); + if (pageSize == -1) { + return UInt32_FALSE; + } + + // 计算对齐后的内存大小(与分配时相同的计算方式) + size_t alignedSize = (templateSize + (size_t)pageSize - 1) & ~((size_t)pageSize - 1); + + // 防止整数溢出 + if (alignedSize > SIZE_MAX / 2) { + return UInt32_FALSE; + } + + // 计算实际分配的总内存大小(2倍对齐大小) + size_t totalSize = 2 * alignedSize; + + // 释放内存 + if (munmap(pBaseAddress, totalSize) == -1) { + return UInt32_FALSE; + } + + return UInt32_TRUE; #else PORTABILITY_ASSERT("UNIXTODO: Implement this function"); #endif