diff --git a/eng/native/configurecompiler.cmake b/eng/native/configurecompiler.cmake index 1d446066476f3e..656a853f44ab75 100644 --- a/eng/native/configurecompiler.cmake +++ b/eng/native/configurecompiler.cmake @@ -325,9 +325,16 @@ if(CLR_CMAKE_HOST_LINUX) add_compile_options($<$:-Wa,--noexecstack>) add_linker_flag(-Wl,--build-id=sha1) add_linker_flag(-Wl,-z,relro,-z,now) -elseif(CLR_CMAKE_HOST_FREEBSD OR CLR_CMAKE_HOST_OPENBSD) +elseif(CLR_CMAKE_HOST_FREEBSD) add_compile_options($<$:-Wa,--noexecstack>) add_linker_flag("-Wl,--build-id=sha1") +elseif(CLR_CMAKE_HOST_OPENBSD) + add_compile_options($<$:-Wa,--noexecstack>) + add_linker_flag("-Wl,--build-id=sha1") + # OpenBSD's ld.so can't resolve native TLS relocs in a .so; rely on clang's default + # emulated TLS (don't pass -fno-emulated-tls). + # The PAL's hand-written asm lacks endbr64 landing pads, so disable branch-target CFI. + add_linker_flag("-Wl,-z,nobtcfi") elseif(CLR_CMAKE_HOST_SUNOS) add_compile_options($<$:-Wa,--noexecstack>) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fstack-protector") @@ -847,6 +854,20 @@ 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() +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 98f1ff991d710b..7e0b3dd93a674d 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..e927956fd04928 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. - + - + @@ -267,6 +269,10 @@ 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..8fd36f1a78ee27 100644 --- a/src/coreclr/nativeaot/CMakeLists.txt +++ b/src/coreclr/nativeaot/CMakeLists.txt @@ -28,6 +28,12 @@ if(CLR_CMAKE_TARGET_ANDROID) set(FEATURE_JAVAMARSHAL 1) endif() +if(CLR_CMAKE_TARGET_OPENBSD) + # OpenBSD's ld.so cannot resolve native TLS relocations in shared objects and has no + # __tls_get_addr, so the runtime must use emulated TLS (like Android). + add_definitions(-DFEATURE_EMULATED_TLS) +endif() + if(NOT DEFINED FEATURE_JAVAMARSHAL) set(FEATURE_JAVAMARSHAL $,1,0>) endif() diff --git a/src/coreclr/nativeaot/Runtime/CMakeLists.txt b/src/coreclr/nativeaot/Runtime/CMakeLists.txt index e491f54a562445..2b72378c6042cf 100644 --- a/src/coreclr/nativeaot/Runtime/CMakeLists.txt +++ b/src/coreclr/nativeaot/Runtime/CMakeLists.txt @@ -288,7 +288,10 @@ if(CLR_CMAKE_TARGET_WIN32) add_compile_options($<$:/safeseh>) endif() else() - if(NOT CLR_CMAKE_TARGET_APPLE AND NOT CLR_CMAKE_TARGET_ARCH_WASM) + # OpenBSD marks the main executable's read-only segments immutable (mimmutable) at load, + # so the runtime cannot mprotect the read-only GS cookie page to writable to initialize it. + # Keep the cookie in writable memory there, like Apple. + if(NOT CLR_CMAKE_TARGET_APPLE AND NOT CLR_CMAKE_TARGET_ARCH_WASM AND NOT CLR_CMAKE_TARGET_OPENBSD) add_definitions(-DFEATURE_READONLY_GS_COOKIE) endif() include(unix/configure.cmake) diff --git a/src/coreclr/nativeaot/Runtime/unix/NativeContext.cpp b/src/coreclr/nativeaot/Runtime/unix/NativeContext.cpp index d1a6b300054622..d5fa9904b90ad3 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,16 @@ #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_NATIVE(nativeContext) (*(nativeContext)) +#else +#define MCONTEXT_FROM_NATIVE(nativeContext) ((nativeContext)->uc_mcontext) +#endif + #if defined(HOST_AMD64) #define ASSIGN_CONTROL_REGS \ ASSIGN_REG(Rip, IP) \ @@ -540,8 +573,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_NATIVE(nativeContext)) = arg0Reg; \ + MCREG_Rsi(MCONTEXT_FROM_NATIVE(nativeContext)) = arg1Reg; #elif defined(HOST_X86) #define ASSIGN_CONTROL_REGS \ @@ -662,7 +695,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_NATIVE(nativeContext)); ASSIGN_CONTROL_REGS ASSIGN_INTEGER_REGS #undef ASSIGN_REG @@ -673,7 +706,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_NATIVE(nativeContext)) = palContext->regPal; ASSIGN_CONTROL_REGS #undef ASSIGN_REG ASSIGN_TWO_ARGUMENT_REGS(arg0Reg, arg1Reg); @@ -694,37 +727,37 @@ uint64_t GetRegisterValueByIndex(void* context, uint32_t index) switch (index) { case 0: - return MCREG_Rax(nativeContext->uc_mcontext); + return MCREG_Rax(MCONTEXT_FROM_NATIVE(nativeContext)); case 1: - return MCREG_Rcx(nativeContext->uc_mcontext); + return MCREG_Rcx(MCONTEXT_FROM_NATIVE(nativeContext)); case 2: - return MCREG_Rdx(nativeContext->uc_mcontext); + return MCREG_Rdx(MCONTEXT_FROM_NATIVE(nativeContext)); case 3: - return MCREG_Rbx(nativeContext->uc_mcontext); + return MCREG_Rbx(MCONTEXT_FROM_NATIVE(nativeContext)); case 4: - return MCREG_Rsp(nativeContext->uc_mcontext); + return MCREG_Rsp(MCONTEXT_FROM_NATIVE(nativeContext)); case 5: - return MCREG_Rbp(nativeContext->uc_mcontext); + return MCREG_Rbp(MCONTEXT_FROM_NATIVE(nativeContext)); case 6: - return MCREG_Rsi(nativeContext->uc_mcontext); + return MCREG_Rsi(MCONTEXT_FROM_NATIVE(nativeContext)); case 7: - return MCREG_Rdi(nativeContext->uc_mcontext); + return MCREG_Rdi(MCONTEXT_FROM_NATIVE(nativeContext)); case 8: - return MCREG_R8(nativeContext->uc_mcontext); + return MCREG_R8(MCONTEXT_FROM_NATIVE(nativeContext)); case 9: - return MCREG_R9(nativeContext->uc_mcontext); + return MCREG_R9(MCONTEXT_FROM_NATIVE(nativeContext)); case 10: - return MCREG_R10(nativeContext->uc_mcontext); + return MCREG_R10(MCONTEXT_FROM_NATIVE(nativeContext)); case 11: - return MCREG_R11(nativeContext->uc_mcontext); + return MCREG_R11(MCONTEXT_FROM_NATIVE(nativeContext)); case 12: - return MCREG_R12(nativeContext->uc_mcontext); + return MCREG_R12(MCONTEXT_FROM_NATIVE(nativeContext)); case 13: - return MCREG_R13(nativeContext->uc_mcontext); + return MCREG_R13(MCONTEXT_FROM_NATIVE(nativeContext)); case 14: - return MCREG_R14(nativeContext->uc_mcontext); + return MCREG_R14(MCONTEXT_FROM_NATIVE(nativeContext)); case 15: - return MCREG_R15(nativeContext->uc_mcontext); + return MCREG_R15(MCONTEXT_FROM_NATIVE(nativeContext)); } ASSERT(false); @@ -735,7 +768,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_NATIVE(nativeContext)); } #endif // HOST_AMD64 @@ -777,23 +810,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_NATIVE(&ctx)); } + uint64_t& NATIVE_CONTEXT::Rcx(){ return (uint64_t&)MCREG_Rcx(MCONTEXT_FROM_NATIVE(&ctx)); } + uint64_t& NATIVE_CONTEXT::Rdx(){ return (uint64_t&)MCREG_Rdx(MCONTEXT_FROM_NATIVE(&ctx)); } + uint64_t& NATIVE_CONTEXT::Rbx(){ return (uint64_t&)MCREG_Rbx(MCONTEXT_FROM_NATIVE(&ctx)); } + uint64_t& NATIVE_CONTEXT::Rsp(){ return (uint64_t&)MCREG_Rsp(MCONTEXT_FROM_NATIVE(&ctx)); } + uint64_t& NATIVE_CONTEXT::Rbp(){ return (uint64_t&)MCREG_Rbp(MCONTEXT_FROM_NATIVE(&ctx)); } + uint64_t& NATIVE_CONTEXT::Rsi(){ return (uint64_t&)MCREG_Rsi(MCONTEXT_FROM_NATIVE(&ctx)); } + uint64_t& NATIVE_CONTEXT::Rdi(){ return (uint64_t&)MCREG_Rdi(MCONTEXT_FROM_NATIVE(&ctx)); } + uint64_t& NATIVE_CONTEXT::R8(){ return (uint64_t&)MCREG_R8(MCONTEXT_FROM_NATIVE(&ctx)); } + uint64_t& NATIVE_CONTEXT::R9(){ return (uint64_t&)MCREG_R9(MCONTEXT_FROM_NATIVE(&ctx)); } + uint64_t& NATIVE_CONTEXT::R10(){ return (uint64_t&)MCREG_R10(MCONTEXT_FROM_NATIVE(&ctx)); } + uint64_t& NATIVE_CONTEXT::R11(){ return (uint64_t&)MCREG_R11(MCONTEXT_FROM_NATIVE(&ctx)); } + uint64_t& NATIVE_CONTEXT::R12(){ return (uint64_t&)MCREG_R12(MCONTEXT_FROM_NATIVE(&ctx)); } + uint64_t& NATIVE_CONTEXT::R13(){ return (uint64_t&)MCREG_R13(MCONTEXT_FROM_NATIVE(&ctx)); } + uint64_t& NATIVE_CONTEXT::R14(){ return (uint64_t&)MCREG_R14(MCONTEXT_FROM_NATIVE(&ctx)); } + uint64_t& NATIVE_CONTEXT::R15(){ return (uint64_t&)MCREG_R15(MCONTEXT_FROM_NATIVE(&ctx)); } + uint64_t& NATIVE_CONTEXT::Rip(){ return (uint64_t&)MCREG_Rip(MCONTEXT_FROM_NATIVE(&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/inc/pal.h b/src/coreclr/pal/inc/pal.h index b724fbc9dede76..2abfc57d0d3f3e 100644 --- a/src/coreclr/pal/inc/pal.h +++ b/src/coreclr/pal/inc/pal.h @@ -3513,7 +3513,15 @@ PAL_FreeExceptionRecords( #define EXCEPTION_EXECUTE_HANDLER 1 #define EXCEPTION_CONTINUE_EXECUTION -1 -struct PAL_SEHException +struct +#ifdef __OpenBSD__ +// OpenBSD's libc++ compares exception type_info by pointer (relying on ld.so to merge +// type_info across shared objects) instead of falling back to a name compare like Linux's +// libstdc++. Default visibility lets ld.so merge type_info into one instance so a +// PAL_SEHException thrown in one PAL DSO is caught in another (e.g. the pal_sxs test). +__attribute__((visibility("default"))) +#endif +PAL_SEHException { private: static const SIZE_T NoTargetFrameSp = (SIZE_T)SIZE_MAX; diff --git a/src/coreclr/pal/inc/unixasmmacrosamd64.inc b/src/coreclr/pal/inc/unixasmmacrosamd64.inc index 90c8947e754297..819ef29ba84257 100644 --- a/src/coreclr/pal/inc/unixasmmacrosamd64.inc +++ b/src/coreclr/pal/inc/unixasmmacrosamd64.inc @@ -430,6 +430,12 @@ C_FUNC(\Name\()_End): .macro INLINE_GETTHREAD // Inlined version of call C_FUNC(RhpGetThread) +#ifdef FEATURE_EMULATED_TLS + // Emulated TLS (e.g. OpenBSD, which has no __tls_get_addr): call a C helper instead + // of inlining the native thread-local access. + call C_FUNC(GetThreadHelper) +#else INLINE_GET_TLS_VAR t_CurrentThreadInfo mov rax, [rax + OFFSETOF__ThreadLocalInfo__m_pThread] +#endif .endm 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/file/file.cpp b/src/coreclr/pal/src/file/file.cpp index b09b3d56d024e3..2ee393980c9dba 100644 --- a/src/coreclr/pal/src/file/file.cpp +++ b/src/coreclr/pal/src/file/file.cpp @@ -420,6 +420,7 @@ CorUnix::InternalCreateFile( int filed = -1; int create_flags = (S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); int open_flags = 0; + int open_flags_for_syscall = 0; // track whether we've created the file with the intended name, // so that it can be removed on failure exit @@ -575,7 +576,22 @@ CorUnix::InternalCreateFile( goto done; } - filed = InternalOpen(lpUnixPath, open_flags, create_flags); + + open_flags_for_syscall = open_flags; +#if defined(__OpenBSD__) + /* On OpenBSD, open() requires O_RDWR or O_WRONLY to be specified along with + O_TRUNC, otherwise it fails with EINVAL. Windows allows truncating a file + that is opened for read-only access (e.g. GENERIC_READ with CREATE_ALWAYS). + Upgrade only the flags passed to open() so the truncation succeeds, while + leaving open_flags (used later for access checks such as file mappings) + unchanged to preserve the caller's requested access. */ + if ((open_flags_for_syscall & O_TRUNC) && (open_flags_for_syscall & O_ACCMODE) == O_RDONLY) + { + open_flags_for_syscall = (open_flags_for_syscall & ~O_ACCMODE) | O_RDWR; + } +#endif // __OpenBSD__ + + filed = InternalOpen(lpUnixPath, open_flags_for_syscall, create_flags); TRACE("Allocated file descriptor [%d]\n", filed); if ( filed < 0 ) 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/safecrt/vsprintf.cpp b/src/coreclr/pal/src/safecrt/vsprintf.cpp index 360222d5dc6798..25cd3766591c35 100644 --- a/src/coreclr/pal/src/safecrt/vsprintf.cpp +++ b/src/coreclr/pal/src/safecrt/vsprintf.cpp @@ -23,6 +23,78 @@ #include #include +#if defined(__OpenBSD__) +// OpenBSD's libc doesn't support the legacy %C/%S wide specifiers (glibc and the +// other BSDs do). Rewrite them to %lc/%ls. Returns a malloc'd copy, or NULL on +// failure (callers fall back to the original format). +static char *PAL_TranslateWideFormatForOpenBSD(const char *format) +{ + size_t length = strlen(format); + // Each rewrite adds one 'l', so doubling is always enough. + char *translated = (char *)malloc(length * 2 + 1); + if (translated == NULL) + { + return NULL; + } + + const char *in = format; + char *out = translated; + while (*in != '\0') + { + if (*in != '%') + { + *out++ = *in++; + continue; + } + + *out++ = *in++; + if (*in == '%') + { + *out++ = *in++; // literal "%%" + continue; + } + + // Skip flags, width, precision and length modifiers. + while (*in != '\0' && strchr("-+ #0123456789.*hlLwIqjzt", *in) != NULL) + { + *out++ = *in++; + } + + if (*in == 'C') + { + *out++ = 'l'; + *out++ = 'c'; + in++; + } + else if (*in == 'S') + { + *out++ = 'l'; + *out++ = 's'; + in++; + } + else if (*in != '\0') + { + *out++ = *in++; + } + } + *out = '\0'; + + return translated; +} + +static int PAL_safecrt_vsnprintf(char *string, size_t count, const char *format, va_list ap) +{ + char *translated = PAL_TranslateWideFormatForOpenBSD(format); + int retvalue = vsnprintf(string, count, translated != NULL ? translated : format, ap); + free(translated); + return retvalue; +} + +#define PAL_SAFECRT_VSNPRINTF PAL_safecrt_vsnprintf +#else // !defined(__OpenBSD__) +#define PAL_SAFECRT_VSNPRINTF vsnprintf +#endif // defined(__OpenBSD__) + DLLEXPORT int __cdecl vsprintf_s ( char *string, size_t sizeInBytes, @@ -36,7 +108,7 @@ DLLEXPORT int __cdecl vsprintf_s ( _VALIDATE_RETURN(format != NULL, EINVAL, -1); _VALIDATE_RETURN(string != NULL && sizeInBytes > 0, EINVAL, -1); - retvalue = vsnprintf(string, sizeInBytes, format, ap); + retvalue = PAL_SAFECRT_VSNPRINTF(string, sizeInBytes, format, ap); if (retvalue < 0) { string[0] = '\0'; @@ -77,7 +149,7 @@ DLLEXPORT int __cdecl _vsnprintf_s ( if (sizeInBytes > count) { save_errno = errno; - retvalue = vsnprintf(string, count + 1, format, ap); + retvalue = PAL_SAFECRT_VSNPRINTF(string, count + 1, format, ap); if (retvalue > (int)(count + 1)) { /* the string has been truncated, return -1 */ @@ -92,7 +164,7 @@ DLLEXPORT int __cdecl _vsnprintf_s ( else /* sizeInBytes <= count */ { save_errno = errno; - retvalue = vsnprintf(string, sizeInBytes, format, ap); + retvalue = PAL_SAFECRT_VSNPRINTF(string, sizeInBytes, format, ap); string[sizeInBytes - 1] = '\0'; /* we allow truncation if count == _TRUNCATE */ if (retvalue >= (int)sizeInBytes && count == _TRUNCATE) 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/pal/src/thread/thread.cpp b/src/coreclr/pal/src/thread/thread.cpp index f7174e69ba5be0..5460b784aa09df 100644 --- a/src/coreclr/pal/src/thread/thread.cpp +++ b/src/coreclr/pal/src/thread/thread.cpp @@ -2372,7 +2372,9 @@ CPalThread::GetStackLimit() int status = pthread_stackseg_np(pthread_self(), &stack); _ASSERT_MSG(status == 0, "pthread_stackseg_np call failed"); - stackLimit = (void*)stack.ss_size; + // ss_sp is the stack base (highest address) and ss_size is the size, so the + // limit (lowest address) is ss_sp - ss_size. The stack grows down from ss_sp. + stackLimit = (void*)((size_t)stack.ss_sp - stack.ss_size); #else pthread_attr_t attr; size_t stackSize; diff --git a/src/coreclr/pal/tests/palsuite/CMakeLists.txt b/src/coreclr/pal/tests/palsuite/CMakeLists.txt index b80c283430f6e2..b52e743d5e3ddd 100644 --- a/src/coreclr/pal/tests/palsuite/CMakeLists.txt +++ b/src/coreclr/pal/tests/palsuite/CMakeLists.txt @@ -400,6 +400,14 @@ target_link_libraries(paltests ${COMMON_TEST_LIBRARIES} ) +if(CLR_CMAKE_TARGET_OPENBSD) + # A few PAL tests (e.g. VirtualAlloc/VirtualProtect) deliberately request simultaneous + # W+X (PAGE_EXECUTE_READWRITE) mappings to exercise the PAL API. OpenBSD rejects those + # unless the binary carries the PT_OPENBSD_WXNEEDED note and runs from a wxallowed mount. + # The runtime itself never needs this (it uses W^X double-mapping), so scope it here. + target_link_options(paltests PRIVATE "-Wl,-z,wxneeded") +endif(CLR_CMAKE_TARGET_OPENBSD) + install (TARGETS paltests DESTINATION paltests COMPONENT paltests EXCLUDE_FROM_ALL) add_dependencies(paltests_install paltests) install (PROGRAMS runpaltests.sh runpaltestshelix.sh DESTINATION paltests COMPONENT paltests EXCLUDE_FROM_ALL) diff --git a/src/coreclr/pal/tests/palsuite/exception_handling/pal_sxs/test1/CMakeLists.txt b/src/coreclr/pal/tests/palsuite/exception_handling/pal_sxs/test1/CMakeLists.txt index cda9df41a65e09..94bb721965e43b 100644 --- a/src/coreclr/pal/tests/palsuite/exception_handling/pal_sxs/test1/CMakeLists.txt +++ b/src/coreclr/pal/tests/palsuite/exception_handling/pal_sxs/test1/CMakeLists.txt @@ -4,6 +4,14 @@ if(CLR_CMAKE_HOST_UNIX) add_definitions(-DFEATURE_ENABLE_HARDWARE_EXCEPTIONS) endif(CLR_CMAKE_HOST_UNIX) +# OpenBSD's libc++ compares exception type_info by pointer and relies on ld.so merging it +# across DSOs. Each side-by-side DSO statically links the PAL, so export PAL_SEHException's +# type_info (default visibility, see pal.h) from both via an extra version script while the +# generated one keeps the rest of the PAL private. +if(CLR_CMAKE_TARGET_OPENBSD) + set(SXS_EXPORT_EXCEPTION_TYPEINFO -Wl,--version-script=${CMAKE_CURRENT_SOURCE_DIR}/openbsd_exception_typeinfo.exports) +endif(CLR_CMAKE_TARGET_OPENBSD) + # Set the RPATH of paltest_pal_sxs_test1 so that it can find dependencies without needing to set LD_LIBRARY # For more information: http://www.cmake.org/Wiki/CMake_RPATH_handling. if(CORECLR_SET_RPATH) @@ -32,6 +40,7 @@ set(DLL1SOURCES dlltest1.cpp) add_library_clr(paltest_pal_sxs_test1_dll1 SHARED EXCLUDE_FROM_ALL ${DLL1SOURCES}) add_custom_target(dlltest1_exports DEPENDS ${EXPORTS_FILE1}) set_property(TARGET paltest_pal_sxs_test1_dll1 APPEND_STRING PROPERTY LINK_FLAGS ${EXPORTS_LINKER_OPTION1}) +set_property(TARGET paltest_pal_sxs_test1_dll1 APPEND_STRING PROPERTY LINK_FLAGS " ${SXS_EXPORT_EXCEPTION_TYPEINFO}") set_property(TARGET paltest_pal_sxs_test1_dll1 APPEND_STRING PROPERTY LINK_DEPENDS ${EXPORTS_FILE1}) add_dependencies(paltest_pal_sxs_test1_dll1 @@ -65,6 +74,7 @@ set(DLL2SOURCES dlltest2.cpp) add_library_clr(paltest_pal_sxs_test1_dll2 SHARED EXCLUDE_FROM_ALL ${DLL2SOURCES}) add_custom_target(dlltest2_exports DEPENDS ${EXPORTS_FILE2}) set_property(TARGET paltest_pal_sxs_test1_dll2 APPEND_STRING PROPERTY LINK_FLAGS ${EXPORTS_LINKER_OPTION2}) +set_property(TARGET paltest_pal_sxs_test1_dll2 APPEND_STRING PROPERTY LINK_FLAGS " ${SXS_EXPORT_EXCEPTION_TYPEINFO}") set_property(TARGET paltest_pal_sxs_test1_dll2 APPEND_STRING PROPERTY LINK_DEPENDS ${EXPORTS_FILE2}) add_dependencies(paltest_pal_sxs_test1_dll2 diff --git a/src/coreclr/pal/tests/palsuite/exception_handling/pal_sxs/test1/exceptionsxs.cpp b/src/coreclr/pal/tests/palsuite/exception_handling/pal_sxs/test1/exceptionsxs.cpp index c538f52235a6f8..d63993f16f3e94 100644 --- a/src/coreclr/pal/tests/palsuite/exception_handling/pal_sxs/test1/exceptionsxs.cpp +++ b/src/coreclr/pal/tests/palsuite/exception_handling/pal_sxs/test1/exceptionsxs.cpp @@ -18,7 +18,7 @@ #include #include -#ifndef __HAIKU__ +#if !defined(__HAIKU__) && !defined(__OpenBSD__) #include #endif diff --git a/src/coreclr/pal/tests/palsuite/exception_handling/pal_sxs/test1/openbsd_exception_typeinfo.exports b/src/coreclr/pal/tests/palsuite/exception_handling/pal_sxs/test1/openbsd_exception_typeinfo.exports new file mode 100644 index 00000000000000..28f39db2d00b73 --- /dev/null +++ b/src/coreclr/pal/tests/palsuite/exception_handling/pal_sxs/test1/openbsd_exception_typeinfo.exports @@ -0,0 +1,5 @@ +{ + global: + _ZTI16PAL_SEHException; + _ZTS16PAL_SEHException; +}; 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/CMakeLists.txt b/src/coreclr/vm/CMakeLists.txt index 7d6945c79e37d9..f8f2c34da22009 100644 --- a/src/coreclr/vm/CMakeLists.txt +++ b/src/coreclr/vm/CMakeLists.txt @@ -17,9 +17,11 @@ include_directories(${CLR_SRC_NATIVE_DIR}/libs/Common) add_definitions(-DUNICODE) add_definitions(-D_UNICODE) -if(CLR_CMAKE_TARGET_ANDROID) +if(CLR_CMAKE_TARGET_ANDROID OR CLR_CMAKE_TARGET_OPENBSD) + # OpenBSD's ld.so cannot resolve native TLS relocations in shared objects and has no + # __tls_get_addr, so the runtime must use emulated TLS (like Android). add_definitions(-DFEATURE_EMULATED_TLS) -endif(CLR_CMAKE_TARGET_ANDROID) +endif() foreach (Config DEBUG CHECKED) add_compile_definitions($<$:WRITE_BARRIER_CHECK>) diff --git a/src/coreclr/vm/amd64/asmhelpers.S b/src/coreclr/vm/amd64/asmhelpers.S index 2d71f26409bc41..17513f82213afa 100644 --- a/src/coreclr/vm/amd64/asmhelpers.S +++ b/src/coreclr/vm/amd64/asmhelpers.S @@ -296,7 +296,7 @@ LEAF_END GetThreadVarsAddress, _TEXT #ifndef TARGET_APPLE # EXTERN_C void* GetTlsIndexObjectDescOffset(); -#ifndef TARGET_ANDROID +#ifndef FEATURE_EMULATED_TLS # # Helper to calculate the offset of native thread local variable `t_ThreadStatics`. The offset has to be found at runtime @@ -320,7 +320,7 @@ LEAF_ENTRY GetTlsIndexObjectDescOffset, _TEXT call EXTERNAL_C_FUNC(__tls_get_addr) # dummy call to have linker see the code pattern to replace the offset int 3 LEAF_END GetTlsIndexObjectDescOffset, _TEXT -#endif // !TARGET_ANDROID +#endif // !FEATURE_EMULATED_TLS #endif // !TARGET_OSX LEAF_ENTRY JIT_PollGC, _TEXT 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/corehost/apphost/static/configure.cmake b/src/native/corehost/apphost/static/configure.cmake index d479257d438740..6734a6e2f54850 100644 --- a/src/native/corehost/apphost/static/configure.cmake +++ b/src/native/corehost/apphost/static/configure.cmake @@ -8,8 +8,8 @@ option(HeimdalGssApi "use heimdal implementation of GssApi" OFF) if (CLR_CMAKE_TARGET_OPENBSD) set(HeimdalGssApi ON) - set(CMAKE_REQUIRED_INCLUDES ${CROSS_ROOTFS}/heimdal/include) - set(CMAKE_PREFIX_PATH ${CROSS_ROOTFS}/heimdal/lib) + set(CMAKE_REQUIRED_INCLUDES ${CROSS_ROOTFS}/usr/local/heimdal/include) + set(CMAKE_PREFIX_PATH ${CROSS_ROOTFS}/usr/local/heimdal/lib) endif() if (HeimdalGssApi) diff --git a/src/native/eventpipe/ds-ipc-pal-socket.c b/src/native/eventpipe/ds-ipc-pal-socket.c index c668c0851f070d..53bd3270af495c 100644 --- a/src/native/eventpipe/ds-ipc-pal-socket.c +++ b/src/native/eventpipe/ds-ipc-pal-socket.c @@ -310,7 +310,7 @@ inline ds_ipc_mode_t ipc_socket_set_default_umask (void) { -#if defined(DS_IPC_PAL_AF_UNIX) && (defined(__APPLE__) || defined(__FreeBSD__)) +#if defined(DS_IPC_PAL_AF_UNIX) && (defined(__APPLE__) || defined(__FreeBSD__) || defined(__OpenBSD__)) // This will set the default permission bit to 600 return umask (~(S_IRUSR | S_IWUSR)); #else @@ -323,7 +323,7 @@ inline void ipc_socket_reset_umask (ds_ipc_mode_t mode) { -#if defined(DS_IPC_PAL_AF_UNIX) && (defined(__APPLE__) || defined(__FreeBSD__)) +#if defined(DS_IPC_PAL_AF_UNIX) && (defined(__APPLE__) || defined(__FreeBSD__) || defined(__OpenBSD__)) umask (mode); #endif } @@ -431,7 +431,7 @@ inline int ipc_socket_set_permission (ds_ipc_socket_t s) { -#if defined(DS_IPC_PAL_AF_UNIX) && !(defined(__APPLE__) || defined(__FreeBSD__) || defined(__HAIKU__)) +#if defined(DS_IPC_PAL_AF_UNIX) && !(defined(__APPLE__) || defined(__FreeBSD__) || defined(__HAIKU__) || defined(__OpenBSD__)) int result_fchmod; DS_ENTER_BLOCKING_PAL_SECTION; do { diff --git a/src/native/libs/System.Net.Security.Native/extra_libs.cmake b/src/native/libs/System.Net.Security.Native/extra_libs.cmake index 23f360d64cd1e1..4fe02e20192e2d 100644 --- a/src/native/libs/System.Net.Security.Native/extra_libs.cmake +++ b/src/native/libs/System.Net.Security.Native/extra_libs.cmake @@ -9,8 +9,7 @@ macro(append_extra_security_libs NativeLibsExtra) set(_heimdal_hints) if (CLR_CMAKE_TARGET_OPENBSD) list(APPEND _heimdal_hints - "${CMAKE_SYSROOT}/heimdal/lib" - "${CMAKE_SYSROOT}/usr/heimdal/lib") + "${CMAKE_SYSROOT}/usr/local/heimdal/lib") endif() if (_heimdal_hints) diff --git a/src/native/libs/System.Security.Cryptography.Native/CMakeLists.txt b/src/native/libs/System.Security.Cryptography.Native/CMakeLists.txt index 720d6237e9dac7..8c6605503a8e98 100644 --- a/src/native/libs/System.Security.Cryptography.Native/CMakeLists.txt +++ b/src/native/libs/System.Security.Cryptography.Native/CMakeLists.txt @@ -19,7 +19,7 @@ add_definitions(-DOPENSSL_API_COMPAT=0x10100000L) # is installed under versioned eopenssl* prefixes. In distro-agnostic mode, # prefer the newest packaged OpenSSL discovered in the sysroot. if (CLR_CMAKE_TARGET_OPENBSD AND FEATURE_DISTRO_AGNOSTIC_SSL) - file(GLOB _openbsd_eopenssl_configs "${CMAKE_SYSROOT}/lib/eopenssl*/cmake/OpenSSL/OpenSSLConfig.cmake") + file(GLOB _openbsd_eopenssl_configs "${CMAKE_SYSROOT}/usr/local/lib/eopenssl*/cmake/OpenSSL/OpenSSLConfig.cmake") if (_openbsd_eopenssl_configs) list(SORT _openbsd_eopenssl_configs) list(REVERSE _openbsd_eopenssl_configs) @@ -34,8 +34,8 @@ if (CLR_CMAKE_TARGET_OPENBSD AND FEATURE_DISTRO_AGNOSTIC_SSL) unset(OPENSSL_SSL_LIBRARY CACHE) set(OpenSSL_DIR "${_openbsd_openssl_dir}" CACHE PATH "OpenSSL config directory" FORCE) - if (EXISTS "${CMAKE_SYSROOT}/include/${_openbsd_openssl_name}") - set(OPENSSL_INCLUDE_DIR "${CMAKE_SYSROOT}/include/${_openbsd_openssl_name}" CACHE PATH "OpenSSL include directory" FORCE) + if (EXISTS "${CMAKE_SYSROOT}/usr/local/include/${_openbsd_openssl_name}") + set(OPENSSL_INCLUDE_DIR "${CMAKE_SYSROOT}/usr/local/include/${_openbsd_openssl_name}" CACHE PATH "OpenSSL include directory" FORCE) endif() endif() endif() diff --git a/src/native/libs/configure.cmake b/src/native/libs/configure.cmake index 22c3837bce100b..4dcb1409f99233 100644 --- a/src/native/libs/configure.cmake +++ b/src/native/libs/configure.cmake @@ -22,8 +22,8 @@ elseif (CLR_CMAKE_TARGET_FREEBSD) include_directories(SYSTEM ${CROSS_ROOTFS}/usr/local/include) set(CMAKE_REQUIRED_INCLUDES ${CROSS_ROOTFS}/usr/local/include) elseif (CLR_CMAKE_TARGET_OPENBSD) - include_directories(SYSTEM ${CROSS_ROOTFS}/usr/local/include ${CROSS_ROOTFS}/heimdal/include) - set(CMAKE_REQUIRED_INCLUDES ${CROSS_ROOTFS}/usr/local/include ${CROSS_ROOTFS}/heimdal/include) + include_directories(SYSTEM ${CROSS_ROOTFS}/usr/local/include ${CROSS_ROOTFS}/usr/local/heimdal/include) + set(CMAKE_REQUIRED_INCLUDES ${CROSS_ROOTFS}/usr/local/include ${CROSS_ROOTFS}/usr/local/heimdal/include) elseif (CLR_CMAKE_TARGET_SUNOS) # requires /opt/tools when building in Global Zone (GZ) include_directories(SYSTEM /opt/local/include /opt/tools/include) 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 ""