Skip to content
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions src/native/libs/System.IO.Compression.Native/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -251,6 +251,10 @@ else ()

endif ()

if (TARGET System.IO.Compression.Native)
target_link_libraries(System.IO.Compression.Native PRIVATE minipal)
endif()

install (TARGETS System.IO.Compression.Native-Static DESTINATION ${STATIC_LIB_DESTINATION} COMPONENT libs)

if(CLR_CMAKE_HOST_ANDROID OR CLR_CMAKE_HOST_IOS OR CLR_CMAKE_HOST_TVOS OR CLR_CMAKE_HOST_MACCATALYST OR CLR_CMAKE_TARGET_BROWSER OR CLR_CMAKE_TARGET_WASI)
Expand Down
14 changes: 4 additions & 10 deletions src/native/minipal/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,11 @@ include(configure.cmake)
set(SOURCES
cpufeatures.c
descriptorlimit.c
entrypoints.c
getexepath.c
memorybarrierprocesswide.c
mutex.c
ospagesize.c
guid.c
random.c
debugger.c
Expand All @@ -18,19 +21,10 @@ set(SOURCES
log.c
)

# ospagesize is provided inline in the header on Windows and WASM; the .c file
# only contains the POSIX implementation. Including it on those platforms would
# produce a redefinition error (mono builds for wasi/browser set HOST_WASM but
# not CLR_CMAKE_TARGET_ARCH_WASM, so check both). In cross-component builds
# (e.g. host=x64, target=wasm) the code runs on the host, so we still need the
# POSIX implementation; only skip when the HOST is actually wasm.
if(NOT WIN32 AND NOT HOST_WASM AND NOT (CLR_CMAKE_TARGET_ARCH_WASM AND NOT CLR_CROSS_COMPONENTS_BUILD))
list(APPEND SOURCES ospagesize.c)
endif()

if(CLR_CMAKE_HOST_UNIX)
list(APPEND SOURCES
cpucount.c
cpuid.c
thread.c
)
endif()
Expand Down
1 change: 1 addition & 0 deletions src/native/minipal/configure.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ check_function_exists(fsync HAVE_FSYNC)

check_symbol_exists(elf_aux_info "sys/auxv.h" HAVE_ELF_AUX_INFO)
check_symbol_exists(arc4random_buf "stdlib.h" HAVE_ARC4RANDOM_BUF)
check_symbol_exists(getauxval "sys/auxv.h" HAVE_GETAUXVAL)
check_symbol_exists(getrandom "sys/random.h" HAVE_GETRANDOM)
check_symbol_exists(getentropy "unistd.h" HAVE_GETENTROPY)
check_symbol_exists(O_CLOEXEC fcntl.h HAVE_O_CLOEXEC)
Expand Down
18 changes: 18 additions & 0 deletions src/native/minipal/cpuid.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

#include "cpuid.h"

#if defined(HOST_X86) || defined(HOST_AMD64)
#if defined(HOST_UNIX)

#if !__has_builtin(__cpuid)
extern void __cpuid(int cpuInfo[4], int function_id);
#endif

#if !__has_builtin(__cpuidex)
extern void __cpuidex(int cpuInfo[4], int function_id, int subFunction_id);
#endif
Comment thread
mdh1418 marked this conversation as resolved.

#endif // HOST_UNIX
#endif // defined(HOST_X86) || defined(HOST_AMD64)
16 changes: 14 additions & 2 deletions src/native/minipal/cpuid.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,19 @@

#include <minipal/utils.h>

#ifdef __cplusplus
extern "C" {
#endif

// MSVC directly defines intrinsics for __cpuid and __cpuidex matching the below signatures
// We define matching signatures for use on Unix platforms.
//
// IMPORTANT: Unlike MSVC, Unix does not explicitly zero ECX for __cpuid

#if !__has_builtin(__cpuid)
static void __cpuid(int cpuInfo[4], int function_id)
inline void __cpuid(int cpuInfo[4], int function_id) __asm("minipal_cpuid");

inline void __cpuid(int cpuInfo[4], int function_id)
{
// Based on the Clang implementation provided in cpuid.h:
// https://github.com/llvm/llvm-project/blob/main/clang/lib/Headers/cpuid.h
Expand All @@ -37,7 +43,9 @@ void __cpuid(int cpuInfo[4], int function_id);
#endif

#if !__has_builtin(__cpuidex)
static void __cpuidex(int cpuInfo[4], int function_id, int subFunction_id)
inline void __cpuidex(int cpuInfo[4], int function_id, int subFunction_id) __asm("minipal_cpuidex");

inline void __cpuidex(int cpuInfo[4], int function_id, int subFunction_id)
{
// Based on the Clang implementation provided in cpuid.h:
// https://github.com/llvm/llvm-project/blob/main/clang/lib/Headers/cpuid.h
Expand All @@ -51,6 +59,10 @@ static void __cpuidex(int cpuInfo[4], int function_id, int subFunction_id)
void __cpuidex(int cpuInfo[4], int function_id, int subFunction_id);
#endif

#ifdef __cplusplus
}
#endif // extern "C"

#endif // HOST_UNIX
#endif // defined(HOST_X86) || defined(HOST_AMD64)

Expand Down
6 changes: 6 additions & 0 deletions src/native/minipal/entrypoints.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

#include "entrypoints.h"

extern const void* minipal_resolve_dllimport(const Entry* resolutionTable, size_t tableLength, const char* name);
10 changes: 9 additions & 1 deletion src/native/minipal/entrypoints.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,11 @@ typedef struct
#define DllImportEntry(impl) \
{#impl, (void*)&impl},

static const void* minipal_resolve_dllimport(const Entry* resolutionTable, size_t tableLength, const char* name)
#ifdef __cplusplus
extern "C" {
#endif

inline const void* minipal_resolve_dllimport(const Entry* resolutionTable, size_t tableLength, const char* name)
{
for (size_t i = 0; i < tableLength; i++)
{
Expand All @@ -31,4 +35,8 @@ static const void* minipal_resolve_dllimport(const Entry* resolutionTable, size_
return NULL;
}

#ifdef __cplusplus
}
#endif // extern "C"

#endif // HAVE_MINIPAL_ENTRYPOINTS_H
183 changes: 183 additions & 0 deletions src/native/minipal/getexepath.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,183 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

#include "minipalconfig.h"
#include "getexepath.h"

#include <errno.h>
#include <limits.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#if defined(__APPLE__)
#include <mach-o/dyld.h>
#elif defined(__FreeBSD__)
#include <sys/param.h>
#include <sys/sysctl.h>
#include <sys/types.h>
#elif defined(__OpenBSD__)
#include <sys/stat.h>
#include <sys/sysctl.h>
#include <unistd.h>
#elif defined(_WIN32)
#include <windows.h>
#elif defined(__HAIKU__)
#include <FindDirectory.h>
#include <StorageDefs.h>
#elif HAVE_GETAUXVAL
#include <sys/auxv.h>
#endif

char* minipal_getexepath(void)
{
#if defined(__APPLE__)
uint32_t len = PATH_MAX;
char pathBuf[PATH_MAX];
if (_NSGetExecutablePath(pathBuf, &len) != 0)
{
errno = EINVAL;
return NULL;
}

return realpath(pathBuf, NULL);
#elif defined(__FreeBSD__)
static const int name[] = { CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, -1 };
char path[PATH_MAX];
size_t len = sizeof(path);
if (sysctl(name, 4, path, &len, NULL, 0) != 0)
{
return NULL;
}

return strdup(path);
#elif defined(__OpenBSD__)
const int name[] = { CTL_KERN, KERN_PROC_ARGS, getpid(), KERN_PROC_ARGV };
size_t len = 0;
if (sysctl(name, 4, NULL, &len, NULL, 0) != 0 || len == 0)
{
return NULL;
}

char *buf = (char *)malloc(len);
if (buf == NULL)
{
return NULL;
}

if (sysctl(name, 4, buf, &len, NULL, 0) != 0)
{
free(buf);
return NULL;
}

// Cast the start of the buffer to access the char * layout safely
char **argv = (char **)buf;
const char *exe = argv[0];

if (strchr(exe, '/') == NULL)
{
const char *p = getenv("PATH");
while (p != NULL && *p != '\0')
{
size_t seg = strcspn(p, ":");
char path[PATH_MAX];

if (snprintf(path, sizeof(path), "%.*s/%s", (int)seg, p, exe) < (int)sizeof(path))
{
struct stat sb;
if (stat(path, &sb) == 0 && S_ISREG(sb.st_mode))
{
char *resolved = realpath(path, NULL);
free(buf);
return resolved;
}
}

p += seg;
if (*p == ':')
p++;
}
}

char *resolved = realpath(exe, NULL);
free(buf);
return resolved;
#elif defined(__sun)
const char* path = getexecname();
if (path == NULL)
{
return NULL;
}

return realpath(path, NULL);
#elif defined(__HAIKU__)
char path[B_PATH_NAME_LENGTH];
status_t status = find_path(B_APP_IMAGE_SYMBOL, B_FIND_PATH_IMAGE_PATH, NULL, path, B_PATH_NAME_LENGTH);
if (status != B_OK)
{
errno = status;
return NULL;
}

return realpath(path, NULL);
#elif defined(_WIN32)
char path[MAX_PATH];
if (GetModuleFileNameA(NULL, path, MAX_PATH) == 0)
{
return NULL;
}

return strdup(path);
#elif defined(TARGET_BROWSER)
const char *browserVirtualAppBase = "/"; // keep in sync other places that define browserVirtualAppBase
return strdup(browserVirtualAppBase);
#elif defined(TARGET_WASI)
// WASI has no /proc, no AT_EXECFN, and argv[0] is unreliable (often "/").
// corerun.wasm is launched with the CORE_ROOT env var set to the directory
// that holds CoreCLR (System.Private.CoreLib.dll and friends). The PAL only
// needs a path whose dirname is that directory, so synthesize one here.
const char* coreRoot = getenv("CORE_ROOT");
if (coreRoot == NULL || coreRoot[0] == '\0')
{
return strdup("/");
}
size_t coreRootLen = strlen(coreRoot);
const char* suffix = "/corerun";
size_t suffixLen = strlen(suffix);
char* result = (char*)malloc(coreRootLen + suffixLen + 1);
if (result == NULL)
{
return NULL;
}
memcpy(result, coreRoot, coreRootLen);
memcpy(result + coreRootLen, suffix, suffixLen + 1);
return result;
#else
#ifdef __linux__
const char* symlinkEntrypointExecutable = "/proc/self/exe";
#else
const char* symlinkEntrypointExecutable = "/proc/curproc/exe";
#endif

// Resolve the symlink to the executable from /proc
char* path = realpath(symlinkEntrypointExecutable, NULL);
if (path)
{
return path;
}

#if HAVE_GETAUXVAL && defined(AT_EXECFN)
// fallback to AT_EXECFN, which does not work properly in rare cases
// when .NET process is set as interpreter (shebang).
const char* exePath = (const char *)(getauxval(AT_EXECFN));
if (exePath)
{
return realpath(exePath, NULL);
}
#endif // HAVE_GETAUXVAL && defined(AT_EXECFN)

return NULL;
#endif // defined(__APPLE__)
}
Loading
Loading