From c330fdc496150e7dcf7f67b41526c4e07ee559af Mon Sep 17 00:00:00 2001 From: Antoine Martin Date: Sat, 12 Nov 2022 00:02:57 -0500 Subject: [PATCH] Mono musl support (backport #76500) --- Directory.Build.props | 2 ++ eng/native/tryrun.cmake | 4 ++- src/coreclr/pal/src/CMakeLists.txt | 5 ++++ src/coreclr/pal/src/misc/perfjitdump.cpp | 2 +- src/coreclr/vm/i386/cgenx86.cpp | 4 +++ src/mono/CMakeLists.txt | 33 ++++++++++++++++++++++++ src/mono/mono.proj | 22 +++++++++++----- src/mono/mono/mini/mini-runtime.c | 29 +++++++++++++++++++++ src/mono/mono/utils/mono-context.h | 8 ++++++ 9 files changed, 100 insertions(+), 9 deletions(-) diff --git a/Directory.Build.props b/Directory.Build.props index c815af2041b714..04fcdf5422a324 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -180,6 +180,8 @@ $(PackageRID) $(_portableOS)-$(TargetArchitecture) + + true diff --git a/eng/native/tryrun.cmake b/eng/native/tryrun.cmake index 96199969da69c9..d6fcc9d3859f19 100644 --- a/eng/native/tryrun.cmake +++ b/eng/native/tryrun.cmake @@ -8,7 +8,9 @@ endmacro() if(EXISTS ${CROSS_ROOTFS}/usr/lib/gcc/armv7-alpine-linux-musleabihf OR EXISTS ${CROSS_ROOTFS}/usr/lib/gcc/armv6-alpine-linux-musleabihf OR - EXISTS ${CROSS_ROOTFS}/usr/lib/gcc/aarch64-alpine-linux-musl) + EXISTS ${CROSS_ROOTFS}/usr/lib/gcc/aarch64-alpine-linux-musl OR + EXISTS ${CROSS_ROOTFS}/usr/lib/gcc/s390x-alpine-linux-musl OR + EXISTS ${CROSS_ROOTFS}/usr/lib/gcc/i586-alpine-linux-musl) set(ALPINE_LINUX 1) elseif(EXISTS ${CROSS_ROOTFS}/bin/freebsd-version) diff --git a/src/coreclr/pal/src/CMakeLists.txt b/src/coreclr/pal/src/CMakeLists.txt index ba13ab392f0c53..b1ff84b29858c3 100644 --- a/src/coreclr/pal/src/CMakeLists.txt +++ b/src/coreclr/pal/src/CMakeLists.txt @@ -319,6 +319,11 @@ if(CLR_CMAKE_TARGET_LINUX) target_link_libraries(coreclrpal ${UNWIND_LIBS}) endif(CLR_CMAKE_USE_SYSTEM_LIBUNWIND) + # bundled libunwind requires using libucontext on alpine and x86 + if(CLR_CMAKE_TARGET_ALPINE_LINUX AND CLR_CMAKE_TARGET_ARCH_I386) + target_link_libraries(coreclrpal ucontext) + endif(CLR_CMAKE_TARGET_ALPINE_LINUX AND CLR_CMAKE_TARGET_ARCH_I386) + endif(CLR_CMAKE_TARGET_LINUX) if(CLR_CMAKE_TARGET_NETBSD) diff --git a/src/coreclr/pal/src/misc/perfjitdump.cpp b/src/coreclr/pal/src/misc/perfjitdump.cpp index d80bd58038cbad..3488397b0da051 100644 --- a/src/coreclr/pal/src/misc/perfjitdump.cpp +++ b/src/coreclr/pal/src/misc/perfjitdump.cpp @@ -25,7 +25,7 @@ #include #include #include -#include +#include #include "../inc/llvm/ELF.h" diff --git a/src/coreclr/vm/i386/cgenx86.cpp b/src/coreclr/vm/i386/cgenx86.cpp index 6af331cc6a351c..9ed3c09645f66c 100644 --- a/src/coreclr/vm/i386/cgenx86.cpp +++ b/src/coreclr/vm/i386/cgenx86.cpp @@ -1163,6 +1163,7 @@ extern "C" DWORD __stdcall xmmYmmStateSupport() #else // !TARGET_UNIX +#if !__has_builtin(__cpuid) void __cpuid(int cpuInfo[4], int function_id) { // Based on the Clang implementation provided in cpuid.h: @@ -1173,7 +1174,9 @@ void __cpuid(int cpuInfo[4], int function_id) : "0"(function_id) ); } +#endif +#if !__has_builtin(__cpuidex) void __cpuidex(int cpuInfo[4], int function_id, int subFunction_id) { // Based on the Clang implementation provided in cpuid.h: @@ -1184,6 +1187,7 @@ void __cpuidex(int cpuInfo[4], int function_id, int subFunction_id) : "0"(function_id), "2"(subFunction_id) ); } +#endif extern "C" DWORD __stdcall xmmYmmStateSupport() { diff --git a/src/mono/CMakeLists.txt b/src/mono/CMakeLists.txt index 49a73b1b709c37..ff0041257c2730 100644 --- a/src/mono/CMakeLists.txt +++ b/src/mono/CMakeLists.txt @@ -208,6 +208,33 @@ elseif(CMAKE_SYSTEM_NAME STREQUAL "Linux") # Enable the "full RELRO" options (RELRO & BIND_NOW) at link time add_link_options(-Wl,-z,relro) add_link_options(-Wl,-z,now) + # Detect Linux ID + set(LINUX_ID_FILE "/etc/os-release") + if(CMAKE_CROSSCOMPILING) + set(LINUX_ID_FILE "${CMAKE_SYSROOT}${LINUX_ID_FILE}") + endif() + + if(EXISTS ${LINUX_ID_FILE}) + execute_process( + COMMAND bash -c "source ${LINUX_ID_FILE} && echo \$ID" + OUTPUT_VARIABLE LINUX_ID + OUTPUT_STRIP_TRAILING_WHITESPACE) + + execute_process( + COMMAND bash -c "if strings \"${CMAKE_SYSROOT}/usr/bin/ldd\" 2>&1 | grep -q musl; then echo musl; fi" + OUTPUT_VARIABLE LINUX_MUSL + OUTPUT_STRIP_TRAILING_WHITESPACE) + endif() + + if(DEFINED LINUX_ID) + if(LINUX_ID STREQUAL alpine) + set(HOST_ALPINE_LINUX 1) + endif() + + if(LINUX_MUSL STREQUAL musl) + set(HOST_LINUX_MUSL 1) + endif() + endif(DEFINED LINUX_ID) elseif(CMAKE_SYSTEM_NAME STREQUAL "Android") set(HOST_LINUX 1) add_definitions(-D_GNU_SOURCE -D_REENTRANT) @@ -784,6 +811,12 @@ if (TARGET_BROWSER) # sys/errno.h exists, but just emits a warning and includes errno.h unset(HAVE_SYS_ERRNO_H) endif() + +if(HOST_ALPINE_LINUX) + # On Alpine Linux, we need to ensure that the reported stack range for the primary thread is + # larger than the initial committed stack size. + add_definitions(-DENSURE_PRIMARY_STACK_SIZE) +endif() ### End of OS specific checks add_subdirectory(mono) diff --git a/src/mono/mono.proj b/src/mono/mono.proj index fb98ffc1896906..83368eefa439ab 100644 --- a/src/mono/mono.proj +++ b/src/mono/mono.proj @@ -417,12 +417,18 @@ <_MonoCFLAGS Include="-Wl,--build-id=sha1" /> + <_MonoCFLAGS Include="-Wno-int-conversion" /> <_MonoCXXFLAGS Include="-Wl,--build-id=sha1" /> <_MonoAOTCFLAGS Include="-Wl,--build-id=sha1" /> + <_MonoAOTCFLAGS Include="-Wno-int-conversion" /> <_MonoAOTCXXFLAGS Include="-Wl,--build-id=sha1" /> + + <_MonoAOTCFLAGS Include="-lucontext" /> + <_MonoCFLAGS Include="-lucontext" /> + @@ -500,16 +506,18 @@ darwin-x86_64 windows-x86_64 <_MonoRuntimeFilePath>$(MonoObjDir)out\lib\$(MonoFileName) - <_LinuxAbi Condition="'$(TargetsAndroid)' != 'true'">gnu - <_LinuxAbi Condition="'$(TargetsAndroid)' == 'true'">android + <_LinuxAbi Condition="'$(TargetsAndroid)' != 'true' and '$(TargetsLinuxMusl)' != 'true'">linux-gnu + <_LinuxAbi Condition="'$(TargetsAndroid)' != 'true' and '$(TargetsLinuxMusl)' == 'true'">alpine-linux-musl + <_LinuxAbi Condition="'$(TargetsAndroid)' == 'true'">linux-android <_LinuxFloatAbi Condition="'$(TargetsAndroid)' != 'true'">hf <_Objcopy>objcopy - <_Objcopy Condition="'$(Platform)' == 'arm'">arm-linux-$(_LinuxAbi)eabi$(_LinuxFloatAbi)-$(_Objcopy) - <_Objcopy Condition="'$(Platform)' == 'arm64'">aarch64-linux-$(_LinuxAbi)-$(_Objcopy) - <_Objcopy Condition="'$(Platform)' == 's390x'">s390x-linux-$(_LinuxAbi)-$(_Objcopy) - <_Objcopy Condition="'$(Platform)' == 'x64'">x86_64-linux-$(_LinuxAbi)-$(_Objcopy) - <_Objcopy Condition="'$(Platform)' == 'x86'">i686-linux-$(_LinuxAbi)-$(_Objcopy) + <_Objcopy Condition="'$(Platform)' == 'arm'">arm-$(_LinuxAbi)eabi$(_LinuxFloatAbi)-$(_Objcopy) + <_Objcopy Condition="'$(Platform)' == 'arm64'">aarch64-$(_LinuxAbi)-$(_Objcopy) + <_Objcopy Condition="'$(Platform)' == 's390x'">s390x-$(_LinuxAbi)-$(_Objcopy) + <_Objcopy Condition="'$(Platform)' == 'x64'">x86_64-$(_LinuxAbi)-$(_Objcopy) + <_Objcopy Condition="'$(Platform)' == 'x86'">i686-$(_LinuxAbi)-$(_Objcopy) <_Objcopy Condition="'$(TargetsAndroid)' == 'true'">$(ANDROID_NDK_ROOT)/toolchains/llvm/prebuilt/$(MonoToolchainPrebuiltOS)/bin/$(_Objcopy) + <_Objcopy Condition="'$(TargetsLinuxMusl)' == 'true' and '$(CrossBuild)' != 'true'">objcopy diff --git a/src/mono/mono/mini/mini-runtime.c b/src/mono/mono/mini/mini-runtime.c index 812a8348c5f438..20a8377c1f5dc8 100644 --- a/src/mono/mono/mini/mini-runtime.c +++ b/src/mono/mono/mini/mini-runtime.c @@ -4313,6 +4313,30 @@ mini_llvm_init (void) #endif } +#ifdef ENSURE_PRIMARY_STACK_SIZE +/*++ + Function: + EnsureStackSize + + Abstract: + This fixes a problem on MUSL where the initial stack size reported by the + pthread_attr_getstack is about 128kB, but this limit is not fixed and + the stack can grow dynamically. The problem is that it makes the + functions ReflectionInvocation::[Try]EnsureSufficientExecutionStack + to fail for real life scenarios like e.g. compilation of corefx. + Since there is no real fixed limit for the stack, the code below + ensures moving the stack limit to a value that makes reasonable + real life scenarios work. + + --*/ +static MONO_NO_OPTIMIZATION MONO_NEVER_INLINE void +ensure_stack_size (size_t size) +{ + volatile uint8_t *s = (uint8_t *)g_alloca(size); + *s = 0; +} +#endif // ENSURE_PRIMARY_STACK_SIZE + void mini_add_profiler_argument (const char *desc) { @@ -4468,6 +4492,11 @@ mini_init (const char *filename, const char *runtime_version) mono_w32handle_init (); #endif +#ifdef ENSURE_PRIMARY_STACK_SIZE + // TODO: https://github.com/dotnet/runtime/issues/72920 + ensure_stack_size (5 * 1024 * 1024); +#endif // ENSURE_PRIMARY_STACK_SIZE + mono_thread_info_runtime_init (&ticallbacks); if (g_hasenv ("MONO_DEBUG")) { diff --git a/src/mono/mono/utils/mono-context.h b/src/mono/mono/utils/mono-context.h index bd1a3cd0104c2a..db4ba452bcb070 100644 --- a/src/mono/mono/utils/mono-context.h +++ b/src/mono/mono/utils/mono-context.h @@ -11,6 +11,14 @@ #ifndef __MONO_MONO_CONTEXT_H__ #define __MONO_MONO_CONTEXT_H__ +/* + * Handle non-gnu libc versions with nothing in features.h + * We have no idea what they're compatible with, so always fail. + */ +#ifndef __GLIBC_PREREQ +# define __GLIBC_PREREQ(x,y) 0 +#endif + #include "mono-compiler.h" #include "mono-sigcontext.h" #include "mono-machine.h"