From 12c47990c76d575f60029005aaf55e53dfe36f4b Mon Sep 17 00:00:00 2001 From: Adeel <3840695+am11@users.noreply.github.com> Date: Sat, 6 Jun 2026 22:28:01 +0300 Subject: [PATCH] Port bootstrap build on OpenBSD --- eng/native/configurecompiler.cmake | 21 ++++ eng/native/functions.cmake | 8 +- src/coreclr/gc/unix/gcenv.unix.cpp | 2 + src/coreclr/hosts/corerun/corerun.hpp | 10 ++ src/coreclr/inc/check.h | 11 +- src/coreclr/inc/check.inl | 11 +- src/coreclr/inc/clrtypes.h | 9 +- src/coreclr/inc/pedecoder.h | 2 + src/coreclr/jit/compiler.hpp | 4 +- src/coreclr/jit/jit.h | 4 +- src/coreclr/minipal/Unix/doublemapping.cpp | 4 +- .../Microsoft.NETCore.Native.Unix.targets | 6 +- src/coreclr/nativeaot/CMakeLists.txt | 9 ++ .../nativeaot/Runtime/unix/NativeContext.cpp | 111 ++++++++++++------ .../nativeaot/Runtime/unix/PalUnix.cpp | 13 ++ .../src/arch/amd64/signalhandlerhelper.cpp | 6 +- src/coreclr/pal/src/exception/signal.cpp | 16 +-- src/coreclr/pal/src/include/pal/context.h | 55 +++++++-- src/coreclr/pal/src/thread/context.cpp | 14 ++- .../tools/Common/CommandLineHelpers.cs | 6 +- .../ObjectWriter/PETargetExtensions.cs | 4 + .../Common/TypeSystem/Common/TargetDetails.cs | 1 + .../ILCompiler.Diagnostics/PerfMapWriter.cs | 1 + .../ReadyToRunDiagnosticsConstants.cs | 1 + .../ObjectWriter/TargetExtensions.cs | 4 + .../ReadyToRunReader.cs | 1 + src/coreclr/tools/r2rdump/Program.cs | 4 +- .../superpmi-shim-collector/CMakeLists.txt | 2 +- src/coreclr/vm/threadstatics.cpp | 8 +- .../pkg/projects/netcoreappRIDs.props | 10 +- src/native/minipal/thread.h | 5 +- src/native/minipal/types.h | 2 +- 32 files changed, 267 insertions(+), 98 deletions(-) diff --git a/eng/native/configurecompiler.cmake b/eng/native/configurecompiler.cmake index 1d446066476f3e..29edd2c42191e7 100644 --- a/eng/native/configurecompiler.cmake +++ b/eng/native/configurecompiler.cmake @@ -847,6 +847,27 @@ else(CLR_CMAKE_TARGET_UNIX) add_compile_definitions($<$>>:TARGET_WINDOWS>) endif(CLR_CMAKE_TARGET_UNIX) +# OpenBSD only exposes its libunwind symbols through the LLVM C++ runtime +# (libc++/libc++abi), so default to those there. An explicit selection via +# CLR_CMAKE_CXX_STANDARD_LIBRARY/CLR_CMAKE_CXX_ABI_LIBRARY (applied by the cross +# toolchain file) still takes precedence. +if(CLR_CMAKE_TARGET_OPENBSD) + if(NOT CLR_CMAKE_CXX_STANDARD_LIBRARY) + add_compile_options($<$:--stdlib=libc++>) + add_link_options($<$:--stdlib=libc++>) + endif() + if(NOT CLR_CMAKE_CXX_ABI_LIBRARY) + add_link_options("LINKER:-lc++abi") + endif() + + # Use native (not emulated) TLS so C/C++ __thread vars match the runtime's assembly. + add_compile_options(-fno-emulated-tls) + + # OpenBSD has no __tls_get_addr (only static TLS). Use initial-exec so general-dynamic + # TLS (and its unresolvable __tls_get_addr reference in shared objects) is never emitted. + add_compile_options(-ftls-model=initial-exec) +endif() + if(CLR_CMAKE_HOST_UNIX_ARM) if (NOT DEFINED CLR_ARM_FPU_TYPE) set(CLR_ARM_FPU_TYPE vfpv3) diff --git a/eng/native/functions.cmake b/eng/native/functions.cmake index f7066de09a764c..5064f51b101220 100644 --- a/eng/native/functions.cmake +++ b/eng/native/functions.cmake @@ -192,7 +192,13 @@ function(find_unwind_libs UnwindLibs) find_library(UNWIND NAMES unwind) if(UNWIND STREQUAL UNWIND-NOTFOUND) - message(FATAL_ERROR "Cannot find libunwind. Try installing libunwind8-dev or libunwind-devel.") + if(CLR_CMAKE_TARGET_OPENBSD) + # On OpenBSD the libunwind symbols are provided by the C++ ABI library + # (libc++abi), so a standalone libunwind is not expected. + set(UNWIND "") + else() + message(FATAL_ERROR "Cannot find libunwind. Try installing libunwind8-dev or libunwind-devel.") + endif() endif() set(${UnwindLibs} ${UNWIND_LIBS} ${UNWIND} PARENT_SCOPE) diff --git a/src/coreclr/gc/unix/gcenv.unix.cpp b/src/coreclr/gc/unix/gcenv.unix.cpp index 575d9cfd9f8ccb..427aecd42e3de1 100644 --- a/src/coreclr/gc/unix/gcenv.unix.cpp +++ b/src/coreclr/gc/unix/gcenv.unix.cpp @@ -1013,11 +1013,13 @@ static size_t GetCurrentVirtualMemorySize() // non zero if it has succeeded, GetVirtualMemoryMaxAddress() if not available size_t GCToOSInterface::GetVirtualMemoryLimit() { +#ifdef RLIMIT_AS rlimit addressSpaceLimit; if ((getrlimit(RLIMIT_AS, &addressSpaceLimit) == 0) && (addressSpaceLimit.rlim_cur != RLIM_INFINITY)) { return addressSpaceLimit.rlim_cur; } +#endif // RLIMIT_AS // No virtual memory limit return GetVirtualMemoryMaxAddress(); diff --git a/src/coreclr/hosts/corerun/corerun.hpp b/src/coreclr/hosts/corerun/corerun.hpp index ec5a978814ec3c..03187959f88b49 100644 --- a/src/coreclr/hosts/corerun/corerun.hpp +++ b/src/coreclr/hosts/corerun/corerun.hpp @@ -384,6 +384,16 @@ class platform_specific_actions final #include #include #include + +// glibc defines the ElfW() macro to select the native-width Elf type, but some +// libcs (e.g. OpenBSD) don't provide it. Fall back to the appropriate fixed-width type. +#ifndef ElfW +#if defined(TARGET_64BIT) +#define ElfW(type) Elf64_##type +#else +#define ElfW(type) Elf32_##type +#endif +#endif // ElfW #endif // CMake generated diff --git a/src/coreclr/inc/check.h b/src/coreclr/inc/check.h index b020f5f3b6f067..826bb46592ee03 100644 --- a/src/coreclr/inc/check.h +++ b/src/coreclr/inc/check.h @@ -1,9 +1,8 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. + // --------------------------------------------------------------------------- // Check.h -// - // // Assertion checking infrastructure // --------------------------------------------------------------------------- @@ -663,7 +662,7 @@ CHECK CheckAligned(UINT value, UINT alignment); CHECK CheckAligned(ULONG value, UINT alignment); #endif CHECK CheckAligned(UINT64 value, UINT alignment); -#ifdef __APPLE__ +#if defined(__APPLE__) || defined(__OpenBSD__) CHECK CheckAligned(SIZE_T value, UINT alignment); #endif CHECK CheckAligned(const void *address, UINT alignment); @@ -673,7 +672,7 @@ CHECK CheckOverflow(UINT value1, UINT value2); CHECK CheckOverflow(ULONG value1, ULONG value2); #endif CHECK CheckOverflow(UINT64 value1, UINT64 value2); -#ifdef __APPLE__ +#if defined(__APPLE__) || defined(__OpenBSD__) CHECK CheckOverflow(SIZE_T value1, SIZE_T value2); #endif #ifndef __wasm__ @@ -689,7 +688,7 @@ CHECK CheckUnderflow(UINT value1, UINT value2); CHECK CheckUnderflow(ULONG value1, ULONG value2); #endif CHECK CheckUnderflow(UINT64 value1, UINT64 value2); -#ifdef __APPLE__ +#if defined(__APPLE__) || defined(__OpenBSD__) CHECK CheckUnderflow(SIZE_T value1, SIZE_T value2); #endif CHECK CheckUnderflow(const void *address, UINT offset); @@ -697,7 +696,7 @@ CHECK CheckUnderflow(const void *address, UINT offset); CHECK CheckUnderflow(const void *address, ULONG offset); #endif CHECK CheckUnderflow(const void *address, UINT64 offset); -#ifdef __APPLE__ +#if defined(__APPLE__) || defined(__OpenBSD__) CHECK CheckUnderflow(const void *address, SIZE_T offset); #endif CHECK CheckUnderflow(const void *address, void *address2); diff --git a/src/coreclr/inc/check.inl b/src/coreclr/inc/check.inl index b0f65c5d218bbd..ad2952d0cb8930 100644 --- a/src/coreclr/inc/check.inl +++ b/src/coreclr/inc/check.inl @@ -156,7 +156,7 @@ inline CHECK CheckAligned(UINT64 value, UINT alignment) CHECK_OK; } -#if defined(__APPLE__) || defined(__wasm__) +#if defined(__APPLE__) || defined(__wasm__) || defined(__OpenBSD__) inline CHECK CheckAligned(SIZE_T value, UINT alignment) { STATIC_CONTRACT_WRAPPER; @@ -192,7 +192,7 @@ inline CHECK CheckOverflow(UINT64 value1, UINT64 value2) CHECK_OK; } -#ifdef __APPLE__ +#if defined(__APPLE__) || defined(__OpenBSD__) inline CHECK CheckOverflow(SIZE_T value1, SIZE_T value2) { CHECK(value1 + value2 >= value1); @@ -237,7 +237,7 @@ inline CHECK CheckOverflow(const void *address, UINT64 offset) CHECK_OK; } -#if defined(__APPLE__) || defined(__wasm__) +#if defined(__APPLE__) || defined(__wasm__) || defined(__OpenBSD__) inline CHECK CheckOverflow(const void *address, SIZE_T offset) { CHECK((UINT64) address + offset >= (UINT64) address); @@ -271,7 +271,7 @@ inline CHECK CheckUnderflow(UINT64 value1, UINT64 value2) CHECK_OK; } -#ifdef __APPLE__ +#if defined(__APPLE__) || defined(__OpenBSD__) inline CHECK CheckUnderflow(SIZE_T value1, SIZE_T value2) { CHECK(value1 - value2 <= value1); @@ -316,7 +316,7 @@ inline CHECK CheckUnderflow(const void *address, UINT64 offset) CHECK_OK; } -#if defined(__APPLE__) || defined(__wasm__) +#if defined(__APPLE__) || defined(__wasm__) || defined(__OpenBSD__) inline CHECK CheckUnderflow(const void *address, SIZE_T offset) { // SIZE_T is 32bit on wasm32 @@ -371,4 +371,3 @@ inline CHECK CheckBounds(const void *rangeBase, UINT32 rangeSize, UINT32 offset, } #endif // CHECK_INL_ - diff --git a/src/coreclr/inc/clrtypes.h b/src/coreclr/inc/clrtypes.h index 80901d8fda5925..546531eb58184c 100644 --- a/src/coreclr/inc/clrtypes.h +++ b/src/coreclr/inc/clrtypes.h @@ -1,5 +1,6 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. + // ================================================================================ // Standard primitive types for CLR code // @@ -275,7 +276,7 @@ inline UINT64 AlignUp(UINT64 value, UINT alignment) return (value+alignment-1)&~(UINT64)(alignment-1); } -#if defined(__APPLE__) || defined(__wasm__) +#if defined(__APPLE__) || defined(__wasm__) || defined(__OpenBSD__) inline SIZE_T AlignUp(SIZE_T value, UINT alignment) { STATIC_CONTRACT_LEAF; @@ -316,7 +317,7 @@ inline uintptr_t AlignDown(uintptr_t value, UINT alignment) } #endif -#ifdef __APPLE__ +#if defined(__APPLE__) || defined(__OpenBSD__) inline SIZE_T AlignDown(SIZE_T value, UINT alignment) { STATIC_CONTRACT_LEAF; @@ -345,7 +346,7 @@ inline UINT AlignmentPad(UINT64 value, UINT alignment) return (UINT) (AlignUp(value, alignment) - value); } -#if defined(__APPLE__) || defined(__wasm__) +#if defined(__APPLE__) || defined(__wasm__) || defined(__OpenBSD__) inline UINT AlignmentPad(SIZE_T value, UINT alignment) { STATIC_CONTRACT_WRAPPER; @@ -378,7 +379,7 @@ inline UINT AlignmentTrim(UINT64 value, UINT alignment) return ((UINT)value)&(alignment-1); } -#if defined(__APPLE__) || defined(__wasm__) +#if defined(__APPLE__) || defined(__wasm__) || defined(__OpenBSD__) inline UINT AlignmentTrim(SIZE_T value, UINT alignment) { STATIC_CONTRACT_LEAF; diff --git a/src/coreclr/inc/pedecoder.h b/src/coreclr/inc/pedecoder.h index a373f90d55d3b1..1a16bc39f1f4c8 100644 --- a/src/coreclr/inc/pedecoder.h +++ b/src/coreclr/inc/pedecoder.h @@ -102,6 +102,8 @@ inline CHECK CheckOverflow(RVA value1, COUNT_T value2) #define IMAGE_FILE_MACHINE_NATIVE_OS_OVERRIDE 0x4644 #elif defined(__FreeBSD__) #define IMAGE_FILE_MACHINE_NATIVE_OS_OVERRIDE 0xADC4 +#elif defined(__OpenBSD__) +#define IMAGE_FILE_MACHINE_NATIVE_OS_OVERRIDE 0xADC5 #elif defined(__linux__) #define IMAGE_FILE_MACHINE_NATIVE_OS_OVERRIDE 0x7B79 #elif defined(__NetBSD__) diff --git a/src/coreclr/jit/compiler.hpp b/src/coreclr/jit/compiler.hpp index 392cdf16b21fe6..f2e502276e40b7 100644 --- a/src/coreclr/jit/compiler.hpp +++ b/src/coreclr/jit/compiler.hpp @@ -141,12 +141,12 @@ inline unsigned genLog2(uint64_t value) return BitOperations::BitScanForward(value); } -#ifdef __APPLE__ +#if defined(__APPLE__) || defined(__OpenBSD__) inline unsigned genLog2(size_t value) { return genLog2((uint64_t)value); } -#endif // __APPLE__ +#endif // __APPLE__ || __OpenBSD__ // Given an unsigned 64-bit value, returns the lower 32-bits in unsigned format // diff --git a/src/coreclr/jit/jit.h b/src/coreclr/jit/jit.h index 5c7f32e258598d..7f2eb2ff8e0c24 100644 --- a/src/coreclr/jit/jit.h +++ b/src/coreclr/jit/jit.h @@ -731,12 +731,12 @@ inline size_t unsigned_abs(ssize_t x) return ((size_t)std::abs((int64_t)x)); } -#ifdef __APPLE__ +#if defined(__APPLE__) || defined(__OpenBSD__) inline size_t unsigned_abs(int64_t x) { return ((size_t)std::abs(x)); } -#endif // __APPLE__ +#endif // __APPLE__ || __OpenBSD__ #endif // TARGET_64BIT /*****************************************************************************/ diff --git a/src/coreclr/minipal/Unix/doublemapping.cpp b/src/coreclr/minipal/Unix/doublemapping.cpp index 26faf9c50cacdd..6c7619c55fa26e 100644 --- a/src/coreclr/minipal/Unix/doublemapping.cpp +++ b/src/coreclr/minipal/Unix/doublemapping.cpp @@ -1,6 +1,5 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -// #include #include @@ -102,6 +101,8 @@ bool VMToOSInterface::CreateDoubleMemoryMapper(void** pHandle, size_t *pMaxExecu // Clip the maximum double mapped memory size to 1/4 of the virtual address space limit. // When such a limit is set, GC reserves 1/2 of it, so we need to leave something // for the rest of the process. +#ifdef RLIMIT_AS + // OpenBSD has no address-space rlimit (RLIMIT_AS), so this clipping is skipped there. struct rlimit virtualAddressSpaceLimit; if ((getrlimit(RLIMIT_AS, &virtualAddressSpaceLimit) == 0) && (virtualAddressSpaceLimit.rlim_cur != RLIM_INFINITY)) { @@ -111,6 +112,7 @@ bool VMToOSInterface::CreateDoubleMemoryMapper(void** pHandle, size_t *pMaxExecu maxDoubleMappedMemorySize = virtualAddressSpaceLimit.rlim_cur; } } +#endif // RLIMIT_AS // Clip the maximum double mapped memory size to the file size limit struct rlimit fileSizeLimit; diff --git a/src/coreclr/nativeaot/BuildIntegration/Microsoft.NETCore.Native.Unix.targets b/src/coreclr/nativeaot/BuildIntegration/Microsoft.NETCore.Native.Unix.targets index 8c429c993788bb..23a4de1c7761b5 100644 --- a/src/coreclr/nativeaot/BuildIntegration/Microsoft.NETCore.Native.Unix.targets +++ b/src/coreclr/nativeaot/BuildIntegration/Microsoft.NETCore.Native.Unix.targets @@ -21,6 +21,7 @@ The .NET Foundation licenses this file to you under the MIT license. ar <_SymbolPrefix Condition="'$(_IsApplePlatform)' == 'true'">_ lld + lld lld lld bfd @@ -65,6 +66,7 @@ The .NET Foundation licenses this file to you under the MIT license. $(CrossCompileArch)-linux-$(CrossCompileAbi) $(CrossCompileArch)-alpine-linux-$(CrossCompileAbi) $(CrossCompileArch)-unknown-freebsd12 + $(CrossCompileArch)-unknown-openbsd @rpath/$(NativeBinaryPrefix)$(TargetName)$(NativeBinaryExt) @@ -222,14 +224,14 @@ The .NET Foundation licenses this file to you under the MIT license. - + - + diff --git a/src/coreclr/nativeaot/CMakeLists.txt b/src/coreclr/nativeaot/CMakeLists.txt index 083cdbf5a29b71..07f4f2dc6d70a5 100644 --- a/src/coreclr/nativeaot/CMakeLists.txt +++ b/src/coreclr/nativeaot/CMakeLists.txt @@ -28,6 +28,15 @@ if(CLR_CMAKE_TARGET_ANDROID) set(FEATURE_JAVAMARSHAL 1) endif() +if(CLR_CMAKE_TARGET_OPENBSD) + # Use native (not emulated) TLS so C/C++ thread locals match the runtime's assembly. + add_compile_options(-fno-emulated-tls) + + # OpenBSD has no __tls_get_addr (only static TLS). Use initial-exec so general-dynamic + # TLS (and its unresolvable __tls_get_addr reference in shared objects) is never emitted. + add_compile_options(-ftls-model=initial-exec) +endif() + if(NOT DEFINED FEATURE_JAVAMARSHAL) set(FEATURE_JAVAMARSHAL $,1,0>) endif() diff --git a/src/coreclr/nativeaot/Runtime/unix/NativeContext.cpp b/src/coreclr/nativeaot/Runtime/unix/NativeContext.cpp index d1a6b300054622..a35588f3f8e9e7 100644 --- a/src/coreclr/nativeaot/Runtime/unix/NativeContext.cpp +++ b/src/coreclr/nativeaot/Runtime/unix/NativeContext.cpp @@ -460,6 +460,29 @@ #define MCREG_T6(mc) ((mc).regs[31]) #define MCREG_Pc(mc) ((mc).pc) +#elif defined(__OpenBSD__) + +// On OpenBSD, ucontext_t is an alias for struct sigcontext and the registers +// are stored directly in it; there is no uc_mcontext sub-structure. The mc +// argument here is the struct sigcontext (i.e. the ucontext) itself. +#define MCREG_Rip(mc) ((mc).sc_rip) +#define MCREG_Rsp(mc) ((mc).sc_rsp) +#define MCREG_Rax(mc) ((mc).sc_rax) +#define MCREG_Rbx(mc) ((mc).sc_rbx) +#define MCREG_Rcx(mc) ((mc).sc_rcx) +#define MCREG_Rdx(mc) ((mc).sc_rdx) +#define MCREG_Rsi(mc) ((mc).sc_rsi) +#define MCREG_Rdi(mc) ((mc).sc_rdi) +#define MCREG_Rbp(mc) ((mc).sc_rbp) +#define MCREG_R8(mc) ((mc).sc_r8) +#define MCREG_R9(mc) ((mc).sc_r9) +#define MCREG_R10(mc) ((mc).sc_r10) +#define MCREG_R11(mc) ((mc).sc_r11) +#define MCREG_R12(mc) ((mc).sc_r12) +#define MCREG_R13(mc) ((mc).sc_r13) +#define MCREG_R14(mc) ((mc).sc_r14) +#define MCREG_R15(mc) ((mc).sc_r15) + #else // For FreeBSD, as found in x86/ucontext.h @@ -526,6 +549,18 @@ #endif // __APPLE__ +// Accessors used to obtain the structure holding the machine registers from a +// ucontext_t. On most platforms the registers live in the uc_mcontext member, +// but on OpenBSD ucontext_t is an alias for struct sigcontext and the registers +// are stored directly in it. +#if defined(__OpenBSD__) +#define MCONTEXT_FROM_PTR(nativeContext) (*(nativeContext)) +#define MCONTEXT_FROM_REF(nativeContext) (nativeContext) +#else +#define MCONTEXT_FROM_PTR(nativeContext) ((nativeContext)->uc_mcontext) +#define MCONTEXT_FROM_REF(nativeContext) ((nativeContext).uc_mcontext) +#endif + #if defined(HOST_AMD64) #define ASSIGN_CONTROL_REGS \ ASSIGN_REG(Rip, IP) \ @@ -540,8 +575,8 @@ ASSIGN_REG(R15, R15) #define ASSIGN_TWO_ARGUMENT_REGS(arg0Reg, arg1Reg) \ - MCREG_Rdi(nativeContext->uc_mcontext) = arg0Reg; \ - MCREG_Rsi(nativeContext->uc_mcontext) = arg1Reg; + MCREG_Rdi(MCONTEXT_FROM_PTR(nativeContext)) = arg0Reg; \ + MCREG_Rsi(MCONTEXT_FROM_PTR(nativeContext)) = arg1Reg; #elif defined(HOST_X86) #define ASSIGN_CONTROL_REGS \ @@ -662,7 +697,7 @@ void NativeContextToPalContext(const void* context, PAL_LIMITED_CONTEXT* palContext) { ucontext_t *nativeContext = (ucontext_t*)context; -#define ASSIGN_REG(regNative, regPal) palContext->regPal = MCREG_##regNative(nativeContext->uc_mcontext); +#define ASSIGN_REG(regNative, regPal) palContext->regPal = MCREG_##regNative(MCONTEXT_FROM_PTR(nativeContext)); ASSIGN_CONTROL_REGS ASSIGN_INTEGER_REGS #undef ASSIGN_REG @@ -673,7 +708,7 @@ void RedirectNativeContext(void* context, const PAL_LIMITED_CONTEXT* palContext, { ucontext_t *nativeContext = (ucontext_t*)context; -#define ASSIGN_REG(regNative, regPal) MCREG_##regNative(nativeContext->uc_mcontext) = palContext->regPal; +#define ASSIGN_REG(regNative, regPal) MCREG_##regNative(MCONTEXT_FROM_PTR(nativeContext)) = palContext->regPal; ASSIGN_CONTROL_REGS #undef ASSIGN_REG ASSIGN_TWO_ARGUMENT_REGS(arg0Reg, arg1Reg); @@ -694,37 +729,37 @@ uint64_t GetRegisterValueByIndex(void* context, uint32_t index) switch (index) { case 0: - return MCREG_Rax(nativeContext->uc_mcontext); + return MCREG_Rax(MCONTEXT_FROM_PTR(nativeContext)); case 1: - return MCREG_Rcx(nativeContext->uc_mcontext); + return MCREG_Rcx(MCONTEXT_FROM_PTR(nativeContext)); case 2: - return MCREG_Rdx(nativeContext->uc_mcontext); + return MCREG_Rdx(MCONTEXT_FROM_PTR(nativeContext)); case 3: - return MCREG_Rbx(nativeContext->uc_mcontext); + return MCREG_Rbx(MCONTEXT_FROM_PTR(nativeContext)); case 4: - return MCREG_Rsp(nativeContext->uc_mcontext); + return MCREG_Rsp(MCONTEXT_FROM_PTR(nativeContext)); case 5: - return MCREG_Rbp(nativeContext->uc_mcontext); + return MCREG_Rbp(MCONTEXT_FROM_PTR(nativeContext)); case 6: - return MCREG_Rsi(nativeContext->uc_mcontext); + return MCREG_Rsi(MCONTEXT_FROM_PTR(nativeContext)); case 7: - return MCREG_Rdi(nativeContext->uc_mcontext); + return MCREG_Rdi(MCONTEXT_FROM_PTR(nativeContext)); case 8: - return MCREG_R8(nativeContext->uc_mcontext); + return MCREG_R8(MCONTEXT_FROM_PTR(nativeContext)); case 9: - return MCREG_R9(nativeContext->uc_mcontext); + return MCREG_R9(MCONTEXT_FROM_PTR(nativeContext)); case 10: - return MCREG_R10(nativeContext->uc_mcontext); + return MCREG_R10(MCONTEXT_FROM_PTR(nativeContext)); case 11: - return MCREG_R11(nativeContext->uc_mcontext); + return MCREG_R11(MCONTEXT_FROM_PTR(nativeContext)); case 12: - return MCREG_R12(nativeContext->uc_mcontext); + return MCREG_R12(MCONTEXT_FROM_PTR(nativeContext)); case 13: - return MCREG_R13(nativeContext->uc_mcontext); + return MCREG_R13(MCONTEXT_FROM_PTR(nativeContext)); case 14: - return MCREG_R14(nativeContext->uc_mcontext); + return MCREG_R14(MCONTEXT_FROM_PTR(nativeContext)); case 15: - return MCREG_R15(nativeContext->uc_mcontext); + return MCREG_R15(MCONTEXT_FROM_PTR(nativeContext)); } ASSERT(false); @@ -735,7 +770,7 @@ uint64_t GetRegisterValueByIndex(void* context, uint32_t index) uint64_t GetPC(void* context) { ucontext_t *nativeContext = (ucontext_t*)context; - return MCREG_Rip(nativeContext->uc_mcontext); + return MCREG_Rip(MCONTEXT_FROM_PTR(nativeContext)); } #endif // HOST_AMD64 @@ -777,23 +812,23 @@ uint64_t GetPC(void* context) uint64_t& NATIVE_CONTEXT::Pc() { return (uint64_t&)MCREG_Pc(ctx.uc_mcontext); } #elif defined(TARGET_AMD64) - uint64_t& NATIVE_CONTEXT::Rax(){ return (uint64_t&)MCREG_Rax(ctx.uc_mcontext); } - uint64_t& NATIVE_CONTEXT::Rcx(){ return (uint64_t&)MCREG_Rcx(ctx.uc_mcontext); } - uint64_t& NATIVE_CONTEXT::Rdx(){ return (uint64_t&)MCREG_Rdx(ctx.uc_mcontext); } - uint64_t& NATIVE_CONTEXT::Rbx(){ return (uint64_t&)MCREG_Rbx(ctx.uc_mcontext); } - uint64_t& NATIVE_CONTEXT::Rsp(){ return (uint64_t&)MCREG_Rsp(ctx.uc_mcontext); } - uint64_t& NATIVE_CONTEXT::Rbp(){ return (uint64_t&)MCREG_Rbp(ctx.uc_mcontext); } - uint64_t& NATIVE_CONTEXT::Rsi(){ return (uint64_t&)MCREG_Rsi(ctx.uc_mcontext); } - uint64_t& NATIVE_CONTEXT::Rdi(){ return (uint64_t&)MCREG_Rdi(ctx.uc_mcontext); } - uint64_t& NATIVE_CONTEXT::R8(){ return (uint64_t&)MCREG_R8(ctx.uc_mcontext); } - uint64_t& NATIVE_CONTEXT::R9(){ return (uint64_t&)MCREG_R9(ctx.uc_mcontext); } - uint64_t& NATIVE_CONTEXT::R10(){ return (uint64_t&)MCREG_R10(ctx.uc_mcontext); } - uint64_t& NATIVE_CONTEXT::R11(){ return (uint64_t&)MCREG_R11(ctx.uc_mcontext); } - uint64_t& NATIVE_CONTEXT::R12(){ return (uint64_t&)MCREG_R12(ctx.uc_mcontext); } - uint64_t& NATIVE_CONTEXT::R13(){ return (uint64_t&)MCREG_R13(ctx.uc_mcontext); } - uint64_t& NATIVE_CONTEXT::R14(){ return (uint64_t&)MCREG_R14(ctx.uc_mcontext); } - uint64_t& NATIVE_CONTEXT::R15(){ return (uint64_t&)MCREG_R15(ctx.uc_mcontext); } - uint64_t& NATIVE_CONTEXT::Rip(){ return (uint64_t&)MCREG_Rip(ctx.uc_mcontext); } + uint64_t& NATIVE_CONTEXT::Rax(){ return (uint64_t&)MCREG_Rax(MCONTEXT_FROM_REF(ctx)); } + uint64_t& NATIVE_CONTEXT::Rcx(){ return (uint64_t&)MCREG_Rcx(MCONTEXT_FROM_REF(ctx)); } + uint64_t& NATIVE_CONTEXT::Rdx(){ return (uint64_t&)MCREG_Rdx(MCONTEXT_FROM_REF(ctx)); } + uint64_t& NATIVE_CONTEXT::Rbx(){ return (uint64_t&)MCREG_Rbx(MCONTEXT_FROM_REF(ctx)); } + uint64_t& NATIVE_CONTEXT::Rsp(){ return (uint64_t&)MCREG_Rsp(MCONTEXT_FROM_REF(ctx)); } + uint64_t& NATIVE_CONTEXT::Rbp(){ return (uint64_t&)MCREG_Rbp(MCONTEXT_FROM_REF(ctx)); } + uint64_t& NATIVE_CONTEXT::Rsi(){ return (uint64_t&)MCREG_Rsi(MCONTEXT_FROM_REF(ctx)); } + uint64_t& NATIVE_CONTEXT::Rdi(){ return (uint64_t&)MCREG_Rdi(MCONTEXT_FROM_REF(ctx)); } + uint64_t& NATIVE_CONTEXT::R8(){ return (uint64_t&)MCREG_R8(MCONTEXT_FROM_REF(ctx)); } + uint64_t& NATIVE_CONTEXT::R9(){ return (uint64_t&)MCREG_R9(MCONTEXT_FROM_REF(ctx)); } + uint64_t& NATIVE_CONTEXT::R10(){ return (uint64_t&)MCREG_R10(MCONTEXT_FROM_REF(ctx)); } + uint64_t& NATIVE_CONTEXT::R11(){ return (uint64_t&)MCREG_R11(MCONTEXT_FROM_REF(ctx)); } + uint64_t& NATIVE_CONTEXT::R12(){ return (uint64_t&)MCREG_R12(MCONTEXT_FROM_REF(ctx)); } + uint64_t& NATIVE_CONTEXT::R13(){ return (uint64_t&)MCREG_R13(MCONTEXT_FROM_REF(ctx)); } + uint64_t& NATIVE_CONTEXT::R14(){ return (uint64_t&)MCREG_R14(MCONTEXT_FROM_REF(ctx)); } + uint64_t& NATIVE_CONTEXT::R15(){ return (uint64_t&)MCREG_R15(MCONTEXT_FROM_REF(ctx)); } + uint64_t& NATIVE_CONTEXT::Rip(){ return (uint64_t&)MCREG_Rip(MCONTEXT_FROM_REF(ctx)); } #elif defined(TARGET_ARM) uint64_t& NATIVE_CONTEXT::Pc(){ return (uint64_t&)MCREG_Pc(ctx.uc_mcontext); } diff --git a/src/coreclr/nativeaot/Runtime/unix/PalUnix.cpp b/src/coreclr/nativeaot/Runtime/unix/PalUnix.cpp index 52aaec80d74eab..c6fa26c221a210 100644 --- a/src/coreclr/nativeaot/Runtime/unix/PalUnix.cpp +++ b/src/coreclr/nativeaot/Runtime/unix/PalUnix.cpp @@ -54,6 +54,10 @@ #include #endif +#if defined(__OpenBSD__) +#include +#endif + #if HAVE_LWP_SELF #include #endif @@ -1193,6 +1197,15 @@ bool PalGetMaximumStackBounds(_Out_ void** ppStackLowOut, _Out_ void** ppStackHi // This is a Mac specific method pStackHighOut = pthread_get_stackaddr_np(pthread_self()); pStackLowOut = ((uint8_t *)pStackHighOut - pthread_get_stacksize_np(pthread_self())); +#elif defined(__OpenBSD__) + // OpenBSD provides the stack segment of the current thread via pthread_stackseg_np. + // ss_sp points to the top (highest address) of the stack. + stack_t stack; + int status = pthread_stackseg_np(pthread_self(), &stack); + ASSERT_MSG(status == 0, "pthread_stackseg_np call failed"); + + pStackHighOut = stack.ss_sp; + pStackLowOut = (uint8_t*)stack.ss_sp - stack.ss_size; #else // __APPLE__ pthread_attr_t attr; size_t stackSize; diff --git a/src/coreclr/pal/src/arch/amd64/signalhandlerhelper.cpp b/src/coreclr/pal/src/arch/amd64/signalhandlerhelper.cpp index 3f70c41d1ef93c..f4c62702865419 100644 --- a/src/coreclr/pal/src/arch/amd64/signalhandlerhelper.cpp +++ b/src/coreclr/pal/src/arch/amd64/signalhandlerhelper.cpp @@ -30,7 +30,7 @@ Parameters : void ExecuteHandlerOnCustomStack(int code, siginfo_t *siginfo, void *context, size_t customSp, SignalHandlerWorkerReturnPoint* returnPoint) { ucontext_t *ucontext = (ucontext_t *)context; - size_t faultSp = (size_t)MCREG_Rsp(ucontext->uc_mcontext); + size_t faultSp = (size_t)MCREG_Rsp(MCONTEXT_FROM_NATIVE(ucontext)); _ASSERTE(IS_ALIGNED(faultSp, 8)); @@ -54,8 +54,8 @@ void ExecuteHandlerOnCustomStack(int code, siginfo_t *siginfo, void *context, si size_t* sp = (size_t*)customSp; // Build fake stack frame to enable the stack unwinder to unwind from signal_handler_worker to the faulting instruction - *--sp = (size_t)MCREG_Rip(ucontext->uc_mcontext); - *--sp = (size_t)MCREG_Rbp(ucontext->uc_mcontext); + *--sp = (size_t)MCREG_Rip(MCONTEXT_FROM_NATIVE(ucontext)); + *--sp = (size_t)MCREG_Rbp(MCONTEXT_FROM_NATIVE(ucontext)); size_t fp = (size_t)sp; *--sp = fakeFrameReturnAddress; diff --git a/src/coreclr/pal/src/exception/signal.cpp b/src/coreclr/pal/src/exception/signal.cpp index c5b6886b562219..79e5629e48c41b 100644 --- a/src/coreclr/pal/src/exception/signal.cpp +++ b/src/coreclr/pal/src/exception/signal.cpp @@ -2,19 +2,11 @@ // The .NET Foundation licenses this file to you under the MIT license. /*++ - - - Module Name: - exception/signal.cpp Abstract: - Signal handler implementation (map signals to exceptions) - - - --*/ #include "pal/dbgmsg.h" @@ -379,7 +371,15 @@ bool IsRunningOnAlternateStack(void *context) { // Note: WSL doesn't return the alternate signal ranges in the uc_stack (the whole structure is zeroed no // matter whether the code is running on an alternate stack or not). So the check would always fail on WSL. +#ifdef TARGET_OPENBSD + // OpenBSD's ucontext_t (struct sigcontext) doesn't carry the signal stack, + // so query the currently installed alternate stack directly. + stack_t signalStackStorage; + stack_t *signalStack = &signalStackStorage; + sigaltstack(NULL, signalStack); +#else stack_t *signalStack = &((native_context_t *)context)->uc_stack; +#endif // Check if the signalStack local variable address is within the alternate stack range. If it is not, // then either the alternate stack was not installed at all or the current method is not running on it. void* alternateStackEnd = (char *)signalStack->ss_sp + signalStack->ss_size; diff --git a/src/coreclr/pal/src/include/pal/context.h b/src/coreclr/pal/src/include/pal/context.h index 9d5e3f01e5f59c..04829d95a17ccf 100644 --- a/src/coreclr/pal/src/include/pal/context.h +++ b/src/coreclr/pal/src/include/pal/context.h @@ -2,19 +2,11 @@ // The .NET Foundation licenses this file to you under the MIT license. /*++ - - - Module Name: - include/pal/context.h Abstract: - Header file for thread context utility functions. - - - --*/ #ifndef _PAL_CONTEXT_H_ @@ -42,6 +34,15 @@ typedef ucontext_t native_context_t; #error Native context type is not known on this platform! #endif // HAVE_UCONTEXT_T +// Helper to obtain the machine-register container from a native_context_t pointer. +// On most platforms the registers live in the uc_mcontext sub-structure. On OpenBSD +// native_context_t is an alias for struct sigcontext and holds the registers directly. +#ifdef TARGET_OPENBSD +#define MCONTEXT_FROM_NATIVE(ucontextPtr) (*(ucontextPtr)) +#else +#define MCONTEXT_FROM_NATIVE(ucontextPtr) ((ucontextPtr)->uc_mcontext) +#endif + #if !HAVE_MACH_EXCEPTIONS #if defined(XSTATE_SUPPORTED) && defined(HOST_AMD64) && !HAVE_PUBLIC_XSTATE_STRUCT @@ -1007,6 +1008,44 @@ inline void *FPREG_Xstate_Hi16Zmm(const ucontext_t *uc, uint32_t *featureSize) #define FPREG_Xmm(uc, index) *(M128A*) &(FPSTATE(uc).fp_fxsave.xmm[index]) #define FPREG_St(uc, index) *(M128A*) &(FPSTATE(uc).fp_fxsave.fp[index].value) +#elif defined(TARGET_OPENBSD) + + // On OpenBSD, ucontext_t is an alias for struct sigcontext and the registers + // are stored directly in it (accessed here via MCONTEXT_FROM_NATIVE). +#define MCREG_Rbp(mc) ((mc).sc_rbp) +#define MCREG_Rip(mc) ((mc).sc_rip) +#define MCREG_Rsp(mc) ((mc).sc_rsp) +#define MCREG_Rsi(mc) ((mc).sc_rsi) +#define MCREG_Rdi(mc) ((mc).sc_rdi) +#define MCREG_Rbx(mc) ((mc).sc_rbx) +#define MCREG_Rdx(mc) ((mc).sc_rdx) +#define MCREG_Rcx(mc) ((mc).sc_rcx) +#define MCREG_Rax(mc) ((mc).sc_rax) +#define MCREG_R8(mc) ((mc).sc_r8) +#define MCREG_R9(mc) ((mc).sc_r9) +#define MCREG_R10(mc) ((mc).sc_r10) +#define MCREG_R11(mc) ((mc).sc_r11) +#define MCREG_R12(mc) ((mc).sc_r12) +#define MCREG_R13(mc) ((mc).sc_r13) +#define MCREG_R14(mc) ((mc).sc_r14) +#define MCREG_R15(mc) ((mc).sc_r15) +#define MCREG_EFlags(mc) ((mc).sc_rflags) +#define MCREG_SegCs(mc) ((mc).sc_cs) + + // from machine/fpu.h: struct fxsave64, referenced via sigcontext::sc_fpstate +#define FPSTATE(uc) ((struct fxsave64*)((uc)->sc_fpstate)) +#define FPREG_ControlWord(uc) FPSTATE(uc)->fx_fcw +#define FPREG_StatusWord(uc) FPSTATE(uc)->fx_fsw +#define FPREG_TagWord(uc) FPSTATE(uc)->fx_ftw +#define FPREG_MxCsr(uc) FPSTATE(uc)->fx_mxcsr +#define FPREG_MxCsr_Mask(uc) FPSTATE(uc)->fx_mxcsr_mask +#define FPREG_ErrorOffset(uc) *(DWORD*) &(FPSTATE(uc)->fx_rip) +#define FPREG_ErrorSelector(uc) *((WORD*) &(FPSTATE(uc)->fx_rip) + 2) +#define FPREG_DataOffset(uc) *(DWORD*) &(FPSTATE(uc)->fx_rdp) +#define FPREG_DataSelector(uc) *((WORD*) &(FPSTATE(uc)->fx_rdp) + 2) + +#define FPREG_Xmm(uc, index) *(M128A*) &(FPSTATE(uc)->fx_xmm[index]) +#define FPREG_St(uc, index) *(M128A*) &(FPSTATE(uc)->fx_st[index]) #else //__APPLE__ // For FreeBSD, as found in x86/ucontext.h diff --git a/src/coreclr/pal/src/thread/context.cpp b/src/coreclr/pal/src/thread/context.cpp index 16964ce4e885ed..259cfb320b174a 100644 --- a/src/coreclr/pal/src/thread/context.cpp +++ b/src/coreclr/pal/src/thread/context.cpp @@ -55,6 +55,10 @@ typedef int __ptrace_request; #include #endif // HAVE_MACHINE_NPX_H +#ifdef __OpenBSD__ +#include +#endif // __OpenBSD__ + #if HAVE_PT_REGS #include #endif // HAVE_PT_REGS @@ -499,7 +503,7 @@ BOOL CONTEXT_GetRegisters(DWORD processId, LPCONTEXT lpContext) #if HAVE_PT_REGS #define ASSIGN_REG(reg) MCREG_##reg(registers.uc_mcontext) = PTREG_##reg(ptrace_registers); #elif HAVE_BSD_REGS_T -#define ASSIGN_REG(reg) MCREG_##reg(registers.uc_mcontext) = BSDREG_##reg(ptrace_registers); +#define ASSIGN_REG(reg) MCREG_##reg(MCONTEXT_FROM_NATIVE(®isters)) = BSDREG_##reg(ptrace_registers); #else #define ASSIGN_REG(reg) ASSERT("Don't know how to get the context of another process on this platform!"); @@ -701,7 +705,7 @@ Return value : --*/ void CONTEXTToNativeContext(CONST CONTEXT *lpContext, native_context_t *native) { -#define ASSIGN_REG(reg) MCREG_##reg(native->uc_mcontext) = lpContext->reg; +#define ASSIGN_REG(reg) MCREG_##reg(MCONTEXT_FROM_NATIVE(native)) = lpContext->reg; if ((lpContext->ContextFlags & CONTEXT_CONTROL) == CONTEXT_CONTROL) { ASSIGN_CONTROL_REGS @@ -1043,7 +1047,7 @@ void CONTEXTFromNativeContext(const native_context_t *native, LPCONTEXT lpContex { lpContext->ContextFlags = contextFlags; -#define ASSIGN_REG(reg) lpContext->reg = MCREG_##reg(native->uc_mcontext); +#define ASSIGN_REG(reg) lpContext->reg = MCREG_##reg(MCONTEXT_FROM_NATIVE(native)); if ((contextFlags & CONTEXT_CONTROL) == CONTEXT_CONTROL) { ASSIGN_CONTROL_REGS @@ -1317,7 +1321,7 @@ Return value : LPVOID GetNativeContextPC(const native_context_t *context) { #ifdef HOST_AMD64 - return (LPVOID)MCREG_Rip(context->uc_mcontext); + return (LPVOID)MCREG_Rip(MCONTEXT_FROM_NATIVE(context)); #elif defined(HOST_X86) return (LPVOID) MCREG_Eip(context->uc_mcontext); #elif defined(HOST_S390X) @@ -1345,7 +1349,7 @@ Return value : LPVOID GetNativeContextSP(const native_context_t *context) { #ifdef HOST_AMD64 - return (LPVOID)MCREG_Rsp(context->uc_mcontext); + return (LPVOID)MCREG_Rsp(MCONTEXT_FROM_NATIVE(context)); #elif defined(HOST_X86) return (LPVOID) MCREG_Esp(context->uc_mcontext); #elif defined(HOST_S390X) diff --git a/src/coreclr/tools/Common/CommandLineHelpers.cs b/src/coreclr/tools/Common/CommandLineHelpers.cs index d13d782327467b..58ff170a7e5252 100644 --- a/src/coreclr/tools/Common/CommandLineHelpers.cs +++ b/src/coreclr/tools/Common/CommandLineHelpers.cs @@ -25,7 +25,7 @@ internal static partial class Helpers { public const string DefaultSystemModule = "System.Private.CoreLib"; - public static string[] ValidOS { get; } = ["windows", "linux", "freebsd", "osx", "maccatalyst", "ios", "iossimulator", "tvos", "tvossimulator", "android", "browser", "wasi"]; + public static string[] ValidOS { get; } = ["windows", "linux", "freebsd", "openbsd", "osx", "maccatalyst", "ios", "iossimulator", "tvos", "tvossimulator", "android", "browser", "wasi"]; public static string[] ValidArchitectures { get; } = ["arm", "armel", "arm64", "x86", "x64", "riscv64", "loongarch64", "wasm"]; public static Dictionary BuildPathDictionary(IReadOnlyList tokens, bool strict) @@ -70,7 +70,8 @@ public static TargetOS GetTargetOS(string token) return TargetOS.OSX; else if (RuntimeInformation.IsOSPlatform(OSPlatform.FreeBSD)) return TargetOS.FreeBSD; - + else if (RuntimeInformation.IsOSPlatform(OSPlatform.Create("OPENBSD"))) + return TargetOS.OpenBSD; throw new NotImplementedException(); } @@ -80,6 +81,7 @@ public static TargetOS GetTargetOS(string token) "win" or "windows" => TargetOS.Windows, "osx" => TargetOS.OSX, "freebsd" => TargetOS.FreeBSD, + "openbsd" => TargetOS.OpenBSD, "maccatalyst" => TargetOS.MacCatalyst, "iossimulator" => TargetOS.iOSSimulator, "ios" => TargetOS.iOS, diff --git a/src/coreclr/tools/Common/Compiler/ObjectWriter/PETargetExtensions.cs b/src/coreclr/tools/Common/Compiler/ObjectWriter/PETargetExtensions.cs index 12f992c29677b8..1a76c9c6b4ac5f 100644 --- a/src/coreclr/tools/Common/Compiler/ObjectWriter/PETargetExtensions.cs +++ b/src/coreclr/tools/Common/Compiler/ObjectWriter/PETargetExtensions.cs @@ -19,6 +19,7 @@ internal enum MachineOSOverride : ushort Apple = 0x4644, FreeBSD = 0xADC4, NetBSD = 0x1993, + OpenBSD = 0xADC5, SunOS = 0x1992, } @@ -125,6 +126,9 @@ public static MachineOSOverride MachineOSOverrideFromTarget(this TargetDetails t case TargetOS.NetBSD: return MachineOSOverride.NetBSD; + case TargetOS.OpenBSD: + return MachineOSOverride.OpenBSD; + default: throw new NotImplementedException(target.OperatingSystem.ToString()); } diff --git a/src/coreclr/tools/Common/TypeSystem/Common/TargetDetails.cs b/src/coreclr/tools/Common/TypeSystem/Common/TargetDetails.cs index fc69a28bdcb977..4c9862cd0c8698 100644 --- a/src/coreclr/tools/Common/TypeSystem/Common/TargetDetails.cs +++ b/src/coreclr/tools/Common/TypeSystem/Common/TargetDetails.cs @@ -22,6 +22,7 @@ public enum TargetOS tvOSSimulator, FreeBSD, NetBSD, + OpenBSD, SunOS, Browser, Wasi diff --git a/src/coreclr/tools/aot/ILCompiler.Diagnostics/PerfMapWriter.cs b/src/coreclr/tools/aot/ILCompiler.Diagnostics/PerfMapWriter.cs index 16f82023ad0b57..a5774d7f37b8a6 100644 --- a/src/coreclr/tools/aot/ILCompiler.Diagnostics/PerfMapWriter.cs +++ b/src/coreclr/tools/aot/ILCompiler.Diagnostics/PerfMapWriter.cs @@ -116,6 +116,7 @@ private static PerfmapTokensForTarget TranslateTargetDetailsToPerfmapConstants(T TargetOS.OSX => PerfMapOSToken.OSX, TargetOS.FreeBSD => PerfMapOSToken.FreeBSD, TargetOS.NetBSD => PerfMapOSToken.NetBSD, + TargetOS.OpenBSD => PerfMapOSToken.OpenBSD, TargetOS.SunOS => PerfMapOSToken.SunOS, _ => throw new NotImplementedException(details.OperatingSystem.ToString()) }; diff --git a/src/coreclr/tools/aot/ILCompiler.Diagnostics/ReadyToRunDiagnosticsConstants.cs b/src/coreclr/tools/aot/ILCompiler.Diagnostics/ReadyToRunDiagnosticsConstants.cs index 281349be80e52e..449b80add0a458 100644 --- a/src/coreclr/tools/aot/ILCompiler.Diagnostics/ReadyToRunDiagnosticsConstants.cs +++ b/src/coreclr/tools/aot/ILCompiler.Diagnostics/ReadyToRunDiagnosticsConstants.cs @@ -32,6 +32,7 @@ public enum PerfMapOSToken : uint FreeBSD = 4, NetBSD = 5, SunOS = 6, + OpenBSD = 7, } public enum PerfMapAbiToken : uint diff --git a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/ObjectWriter/TargetExtensions.cs b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/ObjectWriter/TargetExtensions.cs index ef76a9abcce5bb..d6d5189ef6d1c4 100644 --- a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/ObjectWriter/TargetExtensions.cs +++ b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/ObjectWriter/TargetExtensions.cs @@ -19,6 +19,7 @@ public enum MachineOSOverride : ushort Apple = 0x4644, FreeBSD = 0xADC4, NetBSD = 0x1993, + OpenBSD = 0xADC5, SunOS = 0x1992, } @@ -125,6 +126,9 @@ public static MachineOSOverride MachineOSOverrideFromTarget(this TargetDetails t case TargetOS.NetBSD: return MachineOSOverride.NetBSD; + case TargetOS.OpenBSD: + return MachineOSOverride.OpenBSD; + default: throw new NotImplementedException(target.OperatingSystem.ToString()); } diff --git a/src/coreclr/tools/aot/ILCompiler.Reflection.ReadyToRun/ReadyToRunReader.cs b/src/coreclr/tools/aot/ILCompiler.Reflection.ReadyToRun/ReadyToRunReader.cs index 3fe30ed575c6f8..9ade1797a4088f 100644 --- a/src/coreclr/tools/aot/ILCompiler.Reflection.ReadyToRun/ReadyToRunReader.cs +++ b/src/coreclr/tools/aot/ILCompiler.Reflection.ReadyToRun/ReadyToRunReader.cs @@ -28,6 +28,7 @@ public enum OperatingSystem FreeBSD = 0xADC4, Linux = 0x7B79, NetBSD = 0x1993, + OpenBSD = 0xADC5, SunOS = 0x1992, Windows = 0, Unknown = -1 diff --git a/src/coreclr/tools/r2rdump/Program.cs b/src/coreclr/tools/r2rdump/Program.cs index 73539ee312e886..513f60f4df7854 100644 --- a/src/coreclr/tools/r2rdump/Program.cs +++ b/src/coreclr/tools/r2rdump/Program.cs @@ -241,7 +241,9 @@ public void Dump(ReadyToRunReader r2r) OperatingSystem.Linux => TargetOS.Linux, OperatingSystem.Apple => TargetOS.OSX, OperatingSystem.FreeBSD => TargetOS.FreeBSD, - OperatingSystem.NetBSD => TargetOS.FreeBSD, + OperatingSystem.NetBSD => TargetOS.NetBSD, + OperatingSystem.OpenBSD => TargetOS.OpenBSD, + OperatingSystem.SunOS => TargetOS.SunOS, OperatingSystem.Unknown => TargetOS.Unknown, // Webcil/WASM images don't encode OS _ => throw new NotImplementedException(r2r.OperatingSystem.ToString()), }; diff --git a/src/coreclr/tools/superpmi/superpmi-shim-collector/CMakeLists.txt b/src/coreclr/tools/superpmi/superpmi-shim-collector/CMakeLists.txt index 87383b7dc5cb98..b51f935668ab3d 100644 --- a/src/coreclr/tools/superpmi/superpmi-shim-collector/CMakeLists.txt +++ b/src/coreclr/tools/superpmi/superpmi-shim-collector/CMakeLists.txt @@ -46,7 +46,7 @@ else() generate_exports_file(${SPMI_COLLECTOR_EXPORTS} ${SPMI_COLLECTOR_EXPORTS_FINAL_FILE}) - if(CLR_CMAKE_TARGET_LINUX OR CLR_CMAKE_TARGET_FREEBSD OR CLR_CMAKE_TARGET_NETBSD OR CLR_CMAKE_TARGET_SUNOS) + if(CLR_CMAKE_TARGET_LINUX OR CLR_CMAKE_TARGET_FREEBSD OR CLR_CMAKE_TARGET_NETBSD OR CLR_CMAKE_TARGET_OPENBSD OR CLR_CMAKE_TARGET_SUNOS) # This is required to force using our own PAL, not one that we are loaded with. add_link_options(LINKER:-Bsymbolic) endif() diff --git a/src/coreclr/vm/threadstatics.cpp b/src/coreclr/vm/threadstatics.cpp index e4d94eac463453..9dc21a6f7086b8 100644 --- a/src/coreclr/vm/threadstatics.cpp +++ b/src/coreclr/vm/threadstatics.cpp @@ -1031,6 +1031,8 @@ bool CanJITOptimizeTLSAccess() // Optimization is disabled for FreeBSD/arm64 #elif defined(TARGET_ANDROID) // Optimation is disabled for Android until emulated TLS is supported. +#elif defined(TARGET_OPENBSD) + // Optimization is disabled for OpenBSD, which has no addressable __tls_get_addr. #elif !defined(TARGET_APPLE) && defined(TARGET_UNIX) && (defined(TARGET_ARM64) || defined(TARGET_LOONGARCH64)) bool tlsResolverValid = IsValidTLSResolver(); if (tlsResolverValid) @@ -1172,13 +1174,17 @@ void GetThreadLocalStaticBlocksInfo(CORINFO_THREAD_STATIC_BLOCKS_INFO* pInfo) pInfo->threadVarsSection = GetThreadVarsSectionAddress(); -#elif defined(TARGET_AMD64) +#elif defined(TARGET_AMD64) && !defined(TARGET_OPENBSD) // For Linux/x64, get the address of tls_get_addr system method and the base address // of struct that we will pass to it. pInfo->tlsGetAddrFtnPtr = reinterpret_cast(&__tls_get_addr); pInfo->tlsIndexObject = GetTlsIndexObjectAddress(); +#elif defined(TARGET_OPENBSD) + + // Unreachable: TLS optimization is disabled on OpenBSD (no addressable __tls_get_addr). + #elif defined(TARGET_ARM64) || defined(TARGET_LOONGARCH64) || defined(TARGET_RISCV64) // For Linux arm64/loongarch64/riscv64, just get the offset of thread static variable, and during execution, diff --git a/src/installer/pkg/projects/netcoreappRIDs.props b/src/installer/pkg/projects/netcoreappRIDs.props index 6c84841697b420..b1c09f223536c1 100644 --- a/src/installer/pkg/projects/netcoreappRIDs.props +++ b/src/installer/pkg/projects/netcoreappRIDs.props @@ -9,11 +9,6 @@ arm64 - - - - - x86 @@ -51,6 +46,11 @@ in our runtime.json to enable others to provide them. --> + + + + + armel diff --git a/src/native/minipal/thread.h b/src/native/minipal/thread.h index 2abcb82e72e4a9..bc1e8c39144501 100644 --- a/src/native/minipal/thread.h +++ b/src/native/minipal/thread.h @@ -14,7 +14,10 @@ #if defined(__linux__) #include #include -#elif defined(__FreeBSD__) || defined(__OpenBSD__) +#elif defined(__FreeBSD__) +#include +#elif defined(__OpenBSD__) +#include #include #elif defined(__NetBSD__) #include diff --git a/src/native/minipal/types.h b/src/native/minipal/types.h index 997e9db21c97d6..3fbc6170468e75 100644 --- a/src/native/minipal/types.h +++ b/src/native/minipal/types.h @@ -6,7 +6,7 @@ #include -#if defined(TARGET_32BIT) || defined(TARGET_OSX) || defined(TARGET_WINDOWS) +#if defined(TARGET_32BIT) || defined(TARGET_OSX) || defined(TARGET_WINDOWS) || defined(TARGET_OPENBSD) #define FORMAT_PREFIX "l" #else #define FORMAT_PREFIX ""