未验证 提交 05cd29c8 编写于 作者: A Adeel Mujahid 提交者: GitHub

Share unix getexepath() definition via src/native (#44999)

* Share unix getexepath() definition via src/native

* Address CR feedback

* Remove duplicate property

* Inline variable with single usage

* Fix include path in tests

* Remove unixcoreruncommon static lib dependency

* Merge coreruncommon.{cpp,h} into corerun.cpp

* Include local headers before the first use

* Remove Unix case from (Win32 only) corerun

* Use realpath in getauxval case

* Delete obsolete comment
上级 a4d877e0
......@@ -146,9 +146,7 @@ EOF
scan_build=scan-build
fi
engNativeDir="$__RepoRootDir/eng/native"
cmakeArgs="-DCLR_ENG_NATIVE_DIR=\"$engNativeDir\" $cmakeArgs"
nextCommand="\"$engNativeDir/gen-buildsys.sh\" \"$cmakeDir\" \"$tryrunDir\" \"$intermediatesDir\" $platformArch $__Compiler \"$__CompilerMajorVersion\" \"$__CompilerMinorVersion\" $__BuildType \"$generator\" $scan_build $cmakeArgs"
nextCommand="\"$__RepoRootDir/eng/native/gen-buildsys.sh\" \"$cmakeDir\" \"$tryrunDir\" \"$intermediatesDir\" $platformArch $__Compiler \"$__CompilerMajorVersion\" \"$__CompilerMinorVersion\" $__BuildType \"$generator\" $scan_build $cmakeArgs"
echo "Invoking $nextCommand"
eval $nextCommand
......
get_filename_component(CLR_REPO_ROOT_DIR ${CMAKE_CURRENT_LIST_DIR}/../.. ABSOLUTE)
set(CLR_ENG_NATIVE_DIR ${CMAKE_CURRENT_LIST_DIR})
get_filename_component(CLR_SRC_NATIVE_DIR ${CMAKE_CURRENT_LIST_DIR}/../../src/native ABSOLUTE)
# TO_NATIVE_PATH so it uses backslashes in Windows to avoid getting error,
# as CLR_SRC_NATIVE_DIR is used to specify source files.
file (TO_NATIVE_PATH ${CLR_SRC_NATIVE_DIR} CLR_SRC_NATIVE_DIR)
......@@ -8,6 +8,7 @@ endif()
# Set the project name
project(CoreCLR)
include(../../eng/native/configurepaths.cmake)
include(${CLR_ENG_NATIVE_DIR}/configurecompiler.cmake)
if(MSVC)
......
......@@ -450,10 +450,10 @@ if %__BuildCrossArchNative% EQU 1 (
set "__CMakeBinDir=!__CMakeBinDir:\=/!"
if %__Ninja% EQU 1 (
set __ExtraCmakeArgs="-DCMAKE_BUILD_TYPE=!__BuildType!"
set __ExtraCmakeArgs="-DCMAKE_BUILD_TYPE=!__BuildType!"
)
set __ExtraCmakeArgs=!__ExtraCmakeArgs! %__CMakeClrBuildSubsetArgs% "-DCLR_CROSS_COMPONENTS_BUILD=1" "-DCLR_CMAKE_TARGET_ARCH=%__BuildArch%" "-DCLR_CMAKE_TARGET_OS=%__TargetOS%" "-DCLR_CMAKE_PGO_INSTRUMENT=0" "-DCLR_CMAKE_OPTDATA_PATH=%__PgoOptDataPath%" "-DCLR_CMAKE_PGO_OPTIMIZE=0" "-DCLR_ENG_NATIVE_DIR=%__RepoRootDir%/eng/native" "-DCLR_REPO_ROOT_DIR=%__RepoRootDir%" %__CMakeArgs%
set __ExtraCmakeArgs=!__ExtraCmakeArgs! %__CMakeClrBuildSubsetArgs% "-DCLR_CROSS_COMPONENTS_BUILD=1" "-DCLR_CMAKE_TARGET_ARCH=%__BuildArch%" "-DCLR_CMAKE_TARGET_OS=%__TargetOS%" "-DCLR_CMAKE_PGO_INSTRUMENT=0" "-DCLR_CMAKE_OPTDATA_PATH=%__PgoOptDataPath%" "-DCLR_CMAKE_PGO_OPTIMIZE=0" %__CMakeArgs%
call "%__RepoRootDir%\eng\native\gen-buildsys.cmd" "%__ProjectDir%" "%__CrossCompIntermediatesDir%" %__VSVersion% %__CrossArch% !__ExtraCmakeArgs!
if not !errorlevel! == 0 (
......@@ -512,22 +512,22 @@ if %__BuildCrossArchNative% EQU 1 (
if /i "%__CrossArch2%" == "x86" ( set __VCBuildArch=x86 )
if /i "%__CrossArch2%" == "x64" ( set __VCBuildArch=x86_amd64 )
echo %__MsgPrefix%Using environment: "%__VCToolsRoot%\vcvarsall.bat" !__VCBuildArch!
call "%__VCToolsRoot%\vcvarsall.bat" !__VCBuildArch!
@if defined _echo @echo on
if not exist "%__CrossComp2IntermediatesDir%" md "%__CrossComp2IntermediatesDir%"
if defined __SkipConfigure goto SkipConfigureCrossBuild2
set __CMakeBinDir="%__CrossComponent2BinDir%"
set "__CMakeBinDir=!__CMakeBinDir:\=/!"
if %__Ninja% EQU 1 (
set __ExtraCmakeArgs="-DCMAKE_BUILD_TYPE=!__BuildType!"
set __ExtraCmakeArgs="-DCMAKE_BUILD_TYPE=!__BuildType!"
)
set __ExtraCmakeArgs=!__ExtraCmakeArgs! %__CMakeClrBuildSubsetArgs% "-DCLR_CROSS_COMPONENTS_BUILD=1" "-DCLR_CMAKE_TARGET_ARCH=%__BuildArch%" "-DCLR_CMAKE_TARGET_OS=%__TargetOS%" "-DCLR_CMAKE_PGO_INSTRUMENT=0" "-DCLR_CMAKE_OPTDATA_PATH=%__PgoOptDataPath%" "-DCLR_CMAKE_PGO_OPTIMIZE=0" "-DCMAKE_SYSTEM_VERSION=10.0" "-DCLR_ENG_NATIVE_DIR=%__RepoRootDir%/eng/native" "-DCLR_REPO_ROOT_DIR=%__RepoRootDir%" %__CMakeArgs%
set __ExtraCmakeArgs=!__ExtraCmakeArgs! %__CMakeClrBuildSubsetArgs% "-DCLR_CROSS_COMPONENTS_BUILD=1" "-DCLR_CMAKE_TARGET_ARCH=%__BuildArch%" "-DCLR_CMAKE_TARGET_OS=%__TargetOS%" "-DCLR_CMAKE_PGO_INSTRUMENT=0" "-DCLR_CMAKE_OPTDATA_PATH=%__PgoOptDataPath%" "-DCLR_CMAKE_PGO_OPTIMIZE=0" "-DCMAKE_SYSTEM_VERSION=10.0" %__CMakeArgs%
call "%__RepoRootDir%\eng\native\gen-buildsys.cmd" "%__ProjectDir%" "%__CrossComp2IntermediatesDir%" %__VSVersion% %__CrossArch2% !__ExtraCmakeArgs!
if not !errorlevel! == 0 (
......@@ -620,10 +620,10 @@ if %__BuildNative% EQU 1 (
echo %__MsgPrefix%Regenerating the Visual Studio solution
if %__Ninja% EQU 1 (
set __ExtraCmakeArgs="-DCMAKE_BUILD_TYPE=!__BuildType!"
set __ExtraCmakeArgs="-DCMAKE_BUILD_TYPE=!__BuildType!"
)
set __ExtraCmakeArgs=!__ExtraCmakeArgs! !___CrossBuildDefine! %__CMakeClrBuildSubsetArgs% "-DCLR_CMAKE_PGO_INSTRUMENT=%__PgoInstrument%" "-DCLR_CMAKE_OPTDATA_PATH=%__PgoOptDataPath%" "-DCLR_CMAKE_PGO_OPTIMIZE=%__PgoOptimize%" "-DCLR_ENG_NATIVE_DIR=%__RepoRootDir%/eng/native" "-DCLR_REPO_ROOT_DIR=%__RepoRootDir%" %__CMakeArgs%
set __ExtraCmakeArgs=!__ExtraCmakeArgs! !___CrossBuildDefine! %__CMakeClrBuildSubsetArgs% "-DCLR_CMAKE_PGO_INSTRUMENT=%__PgoInstrument%" "-DCLR_CMAKE_OPTDATA_PATH=%__PgoOptDataPath%" "-DCLR_CMAKE_PGO_OPTIMIZE=%__PgoOptimize%" %__CMakeArgs%
call "%__RepoRootDir%\eng\native\gen-buildsys.cmd" "%__ProjectDir%" "%__IntermediatesDir%" %__VSVersion% %__BuildArch% !__ExtraCmakeArgs!
if not !errorlevel! == 0 (
echo %__ErrMsgPrefix%%__MsgPrefix%Error: failed to generate native component build project!
......
......@@ -246,7 +246,7 @@ check_prereqs
restore_optdata
# Build the coreclr (native) components.
__CMakeArgs="-DCLR_CMAKE_PGO_INSTRUMENT=$__PgoInstrument -DCLR_CMAKE_OPTDATA_PATH=$__PgoOptDataPath -DCLR_CMAKE_PGO_OPTIMIZE=$__PgoOptimize -DCLR_REPO_ROOT_DIR=\"$__RepoRootDir\" $__CMakeArgs"
__CMakeArgs="-DCLR_CMAKE_PGO_INSTRUMENT=$__PgoInstrument -DCLR_CMAKE_OPTDATA_PATH=$__PgoOptDataPath -DCLR_CMAKE_PGO_OPTIMIZE=$__PgoOptimize $__CMakeArgs"
__CMakeArgs="-DCLR_CMAKE_BUILD_SUBSET_JIT=$__BuildJit -DCLR_CMAKE_BUILD_SUBSET_ALLJITS=$__BuildAllJits -DCLR_CMAKE_BUILD_SUBSET_RUNTIME=$__BuildRuntime $__CMakeArgs"
__CMakeArgs="-DCLR_CMAKE_BUILD_TESTS=$__BuildPALTests $__CMakeArgs"
......
......@@ -5,6 +5,5 @@ if(CLR_CMAKE_HOST_WIN32)
add_subdirectory(coreshim)
else(CLR_CMAKE_HOST_WIN32)
add_definitions(-D_FILE_OFFSET_BITS=64)
add_subdirectory(unixcoreruncommon)
add_subdirectory(unixcorerun)
endif(CLR_CMAKE_HOST_WIN32)
project(CoreRun)
set(CMAKE_INCLUDE_CURRENT_DIR ON)
set(CoreRun_SOURCES corerun.cpp logger.cpp)
set(CoreRun_RESOURCES native.rc)
add_definitions(-DFX_VER_INTERNALNAME_STR=CoreRun.exe)
if(CLR_CMAKE_HOST_UNIX)
# This does not compile on Linux yet
if(CAN_BE_COMPILED_ON_LINUX)
_add_executable(CoreRun
${CoreRun_SOURCES}
${CoreRun_RESOURCES}
)
endif(CAN_BE_COMPILED_ON_LINUX)
else()
_add_executable(CoreRun
${CoreRun_SOURCES}
${CoreRun_RESOURCES}
)
target_link_libraries(CoreRun
utilcodestaticnohost
advapi32.lib
oleaut32.lib
uuid.lib
user32.lib
${STATIC_MT_CRT_LIB}
${STATIC_MT_VCRT_LIB}
)
# Can't compile on linux yet so only add for windows
install_clr(TARGETS CoreRun)
endif(CLR_CMAKE_HOST_UNIX)
_add_executable(CoreRun
corerun.cpp logger.cpp
native.rc
)
target_link_libraries(CoreRun
utilcodestaticnohost
advapi32.lib
oleaut32.lib
uuid.lib
user32.lib
${STATIC_MT_CRT_LIB}
${STATIC_MT_VCRT_LIB}
)
install_clr(TARGETS CoreRun)
project(unixcorerun)
include_directories(../unixcoreruncommon)
include_directories("${CLR_SRC_NATIVE_DIR}/common")
include(configure.cmake)
set(CORERUN_SOURCES
corerun.cpp
)
set(CMAKE_INCLUDE_CURRENT_DIR ON)
_add_executable(corerun
${CORERUN_SOURCES}
)
_add_executable(corerun corerun.cpp)
# FreeBSD and NetBSD implement dlopen(3) in libc
if(NOT CLR_CMAKE_TARGET_FREEBSD AND NOT CLR_CMAKE_TARGET_NETBSD)
target_link_libraries(corerun
dl
)
endif(NOT CLR_CMAKE_TARGET_FREEBSD AND NOT CLR_CMAKE_TARGET_NETBSD)
# Libc turns locks into no-ops if pthread was not loaded into process yet. Loading
# pthread by the process executable ensures that all locks are initialized properly.
target_link_libraries(corerun
unixcoreruncommon
)
target_link_libraries(corerun ${CMAKE_DL_LIBS})
# Android implements pthread natively
if(NOT CLR_CMAKE_TARGET_ANDROID)
target_link_libraries(corerun
pthread
)
target_link_libraries(corerun pthread)
endif()
install_clr(TARGETS corerun)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
#include <coreruncommon.h>
#include <cstdlib>
#include <cstring>
#include <assert.h>
#include <dirent.h>
#include <dlfcn.h>
#include <limits.h>
#include <set>
#include <string>
#include <string.h>
#include <sys/stat.h>
#include "coreclrhost.h"
#include <unistd.h>
#ifndef SUCCEEDED
#define SUCCEEDED(Status) ((Status) >= 0)
#endif // !SUCCEEDED
#include <config.h>
#include <getexepath.h>
#if !HAVE_DIRENT_D_TYPE
#define DT_UNKNOWN 0
#define DT_DIR 4
#define DT_REG 8
#define DT_LNK 10
#endif
// Name of the environment variable controlling server GC.
// If set to 1, server GC is enabled on startup. If 0, server GC is
// disabled. Server GC is off by default.
static const char* serverGcVar = "COMPlus_gcServer";
// Name of environment variable to control "System.Globalization.Invariant"
// Set to 1 for Globalization Invariant mode to be true. Default is false.
static const char* globalizationInvariantVar = "CORECLR_GLOBAL_INVARIANT";
bool GetAbsolutePath(const char* path, std::string& absolutePath)
{
bool result = false;
char realPath[PATH_MAX];
if (realpath(path, realPath) != nullptr && realPath[0] != '\0')
{
absolutePath.assign(realPath);
// realpath should return canonicalized path without the trailing slash
assert(absolutePath.back() != '/');
result = true;
}
return result;
}
bool GetDirectory(const char* absolutePath, std::string& directory)
{
directory.assign(absolutePath);
size_t lastSlash = directory.rfind('/');
if (lastSlash != std::string::npos)
{
directory.erase(lastSlash);
return true;
}
return false;
}
bool GetClrFilesAbsolutePath(const char* currentExePath, const char* clrFilesPath, std::string& clrFilesAbsolutePath)
{
std::string clrFilesRelativePath;
const char* clrFilesPathLocal = clrFilesPath;
if (clrFilesPathLocal == nullptr)
{
// There was no CLR files path specified, use the folder of the corerun/coreconsole
if (!GetDirectory(currentExePath, clrFilesRelativePath))
{
perror("Failed to get directory from argv[0]");
return false;
}
clrFilesPathLocal = clrFilesRelativePath.c_str();
// TODO: consider using an env variable (if defined) as a fall-back.
// The windows version of the corerun uses core_root env variable
}
if (!GetAbsolutePath(clrFilesPathLocal, clrFilesAbsolutePath))
{
perror("Failed to convert CLR files path to absolute path");
return false;
}
return true;
}
void AddFilesFromDirectoryToTpaList(const char* directory, std::string& tpaList)
{
const char * const tpaExtensions[] = {
".ni.dll", // Probe for .ni.dll first so that it's preferred if ni and il coexist in the same dir
".dll",
".ni.exe",
".exe",
};
DIR* dir = opendir(directory);
if (dir == nullptr)
{
return;
}
std::set<std::string> addedAssemblies;
// Walk the directory for each extension separately so that we first get files with .ni.dll extension,
// then files with .dll extension, etc.
for (size_t extIndex = 0; extIndex < sizeof(tpaExtensions) / sizeof(tpaExtensions[0]); extIndex++)
{
const char* ext = tpaExtensions[extIndex];
int extLength = strlen(ext);
struct dirent* entry;
// For all entries in the directory
while ((entry = readdir(dir)) != nullptr)
{
#if HAVE_DIRENT_D_TYPE
int dirEntryType = entry->d_type;
#else
int dirEntryType = DT_UNKNOWN;
#endif
// We are interested in files only
switch (dirEntryType)
{
case DT_REG:
break;
// Handle symlinks and file systems that do not support d_type
case DT_LNK:
case DT_UNKNOWN:
{
std::string fullFilename;
fullFilename.append(directory);
fullFilename.append("/");
fullFilename.append(entry->d_name);
struct stat sb;
if (stat(fullFilename.c_str(), &sb) == -1)
{
continue;
}
if (!S_ISREG(sb.st_mode))
{
continue;
}
}
break;
default:
continue;
}
std::string filename(entry->d_name);
// Check if the extension matches the one we are looking for
int extPos = filename.length() - extLength;
if ((extPos <= 0) || (filename.compare(extPos, extLength, ext) != 0))
{
continue;
}
std::string filenameWithoutExt(filename.substr(0, extPos));
// Make sure if we have an assembly with multiple extensions present,
// we insert only one version of it.
if (addedAssemblies.find(filenameWithoutExt) == addedAssemblies.end())
{
addedAssemblies.insert(filenameWithoutExt);
tpaList.append(directory);
tpaList.append("/");
tpaList.append(filename);
tpaList.append(":");
}
}
// Rewind the directory stream to be able to iterate over it for the next extension
rewinddir(dir);
}
closedir(dir);
}
const char* GetEnvValueBoolean(const char* envVariable)
{
const char* envValue = std::getenv(envVariable);
if (envValue == nullptr)
{
envValue = "0";
}
// CoreCLR expects strings "true" and "false" instead of "1" and "0".
return (std::strcmp(envValue, "1") == 0 || strcasecmp(envValue, "true") == 0) ? "true" : "false";
}
static void *TryLoadHostPolicy(const char *hostPolicyPath)
{
#if defined(__APPLE__)
static const char LibrarySuffix[] = ".dylib";
#else // Various Linux-related OS-es
static const char LibrarySuffix[] = ".so";
#endif
std::string hostPolicyCompletePath(hostPolicyPath);
hostPolicyCompletePath.append(LibrarySuffix);
void *libraryPtr = dlopen(hostPolicyCompletePath.c_str(), RTLD_LAZY);
if (libraryPtr == nullptr)
{
fprintf(stderr, "Failed to load mock hostpolicy at path '%s'. Error: %s", hostPolicyCompletePath.c_str(), dlerror());
}
return libraryPtr;
}
int ExecuteManagedAssembly(
const char* currentExeAbsolutePath,
const char* clrFilesAbsolutePath,
const char* managedAssemblyAbsolutePath,
int managedAssemblyArgc,
const char** managedAssemblyArgv)
{
// Indicates failure
int exitCode = -1;
#ifdef HOST_ARM
// libunwind library is used to unwind stack frame, but libunwind for ARM
// does not support ARM vfpv3/NEON registers in DWARF format correctly.
// Therefore let's disable stack unwinding using DWARF information
// See https://github.com/dotnet/runtime/issues/6479
//
// libunwind use following methods to unwind stack frame.
// UNW_ARM_METHOD_ALL 0xFF
// UNW_ARM_METHOD_DWARF 0x01
// UNW_ARM_METHOD_FRAME 0x02
// UNW_ARM_METHOD_EXIDX 0x04
putenv(const_cast<char *>("UNW_ARM_UNWIND_METHOD=6"));
#endif // HOST_ARM
#if defined(__APPLE__)
static const char* const coreClrDll = "libcoreclr.dylib";
#else
static const char* const coreClrDll = "libcoreclr.so";
#endif
std::string coreClrDllPath(clrFilesAbsolutePath);
coreClrDllPath.append("/");
coreClrDllPath.append(coreClrDll);
if (coreClrDllPath.length() >= PATH_MAX)
{
fprintf(stderr, "Absolute path to libcoreclr.so too long\n");
return -1;
}
// Get just the path component of the managed assembly path
std::string appPath;
GetDirectory(managedAssemblyAbsolutePath, appPath);
std::string tpaList;
// Construct native search directory paths
std::string nativeDllSearchDirs(appPath);
char *coreLibraries = getenv("CORE_LIBRARIES");
if (coreLibraries)
{
nativeDllSearchDirs.append(":");
nativeDllSearchDirs.append(coreLibraries);
if (std::strcmp(coreLibraries, clrFilesAbsolutePath) != 0)
{
AddFilesFromDirectoryToTpaList(coreLibraries, tpaList);
}
}
nativeDllSearchDirs.append(":");
nativeDllSearchDirs.append(clrFilesAbsolutePath);
void* hostpolicyLib = nullptr;
char* mockHostpolicyPath = getenv("MOCK_HOSTPOLICY");
if (mockHostpolicyPath)
{
hostpolicyLib = TryLoadHostPolicy(mockHostpolicyPath);
if (hostpolicyLib == nullptr)
{
return -1;
}
}
AddFilesFromDirectoryToTpaList(clrFilesAbsolutePath, tpaList);
void* coreclrLib = dlopen(coreClrDllPath.c_str(), RTLD_NOW | RTLD_LOCAL);
if (coreclrLib != nullptr)
{
coreclr_initialize_ptr initializeCoreCLR = (coreclr_initialize_ptr)dlsym(coreclrLib, "coreclr_initialize");
coreclr_execute_assembly_ptr executeAssembly = (coreclr_execute_assembly_ptr)dlsym(coreclrLib, "coreclr_execute_assembly");
coreclr_shutdown_2_ptr shutdownCoreCLR = (coreclr_shutdown_2_ptr)dlsym(coreclrLib, "coreclr_shutdown_2");
if (initializeCoreCLR == nullptr)
{
fprintf(stderr, "Function coreclr_initialize not found in the libcoreclr.so\n");
}
else if (executeAssembly == nullptr)
{
fprintf(stderr, "Function coreclr_execute_assembly not found in the libcoreclr.so\n");
}
else if (shutdownCoreCLR == nullptr)
{
fprintf(stderr, "Function coreclr_shutdown_2 not found in the libcoreclr.so\n");
}
else
{
// Check whether we are enabling server GC (off by default)
const char* useServerGc = GetEnvValueBoolean(serverGcVar);
// Check Globalization Invariant mode (false by default)
const char* globalizationInvariant = GetEnvValueBoolean(globalizationInvariantVar);
// Allowed property names:
// APPBASE
// - The base path of the application from which the exe and other assemblies will be loaded
//
// TRUSTED_PLATFORM_ASSEMBLIES
// - The list of complete paths to each of the fully trusted assemblies
//
// APP_PATHS
// - The list of paths which will be probed by the assembly loader
//
// APP_NI_PATHS
// - The list of additional paths that the assembly loader will probe for ngen images
//
// NATIVE_DLL_SEARCH_DIRECTORIES
// - The list of paths that will be probed for native DLLs called by PInvoke
//
const char *propertyKeys[] = {
"TRUSTED_PLATFORM_ASSEMBLIES",
"APP_PATHS",
"APP_NI_PATHS",
"NATIVE_DLL_SEARCH_DIRECTORIES",
"System.GC.Server",
"System.Globalization.Invariant",
};
const char *propertyValues[] = {
// TRUSTED_PLATFORM_ASSEMBLIES
tpaList.c_str(),
// APP_PATHS
appPath.c_str(),
// APP_NI_PATHS
appPath.c_str(),
// NATIVE_DLL_SEARCH_DIRECTORIES
nativeDllSearchDirs.c_str(),
// System.GC.Server
useServerGc,
// System.Globalization.Invariant
globalizationInvariant,
};
void* hostHandle;
unsigned int domainId;
int st = initializeCoreCLR(
currentExeAbsolutePath,
"unixcorerun",
sizeof(propertyKeys) / sizeof(propertyKeys[0]),
propertyKeys,
propertyValues,
&hostHandle,
&domainId);
if (!SUCCEEDED(st))
{
fprintf(stderr, "coreclr_initialize failed - status: 0x%08x\n", st);
exitCode = -1;
}
else
{
st = executeAssembly(
hostHandle,
domainId,
managedAssemblyArgc,
managedAssemblyArgv,
managedAssemblyAbsolutePath,
(unsigned int*)&exitCode);
if (!SUCCEEDED(st))
{
fprintf(stderr, "coreclr_execute_assembly failed - status: 0x%08x\n", st);
exitCode = -1;
}
int latchedExitCode = 0;
st = shutdownCoreCLR(hostHandle, domainId, &latchedExitCode);
if (!SUCCEEDED(st))
{
fprintf(stderr, "coreclr_shutdown failed - status: 0x%08x\n", st);
exitCode = -1;
}
if (exitCode != -1)
{
exitCode = latchedExitCode;
}
}
}
}
else
{
const char* error = dlerror();
fprintf(stderr, "dlopen failed to open the libcoreclr.so with error %s\n", error);
}
if (hostpolicyLib)
{
if(dlclose(hostpolicyLib) != 0)
{
fprintf(stderr, "Warning - dlclose of mock hostpolicy failed.\n");
}
}
return exitCode;
}
// Display the command line options
void DisplayUsage()
......@@ -125,13 +547,16 @@ int main(const int argc, const char* argv[])
}
// Make sure we have a full path for argv[0].
std::string argv0AbsolutePath;
if (!GetEntrypointExecutableAbsolutePath(argv0AbsolutePath))
char* path = getexepath();
if (!path)
{
perror("Could not get full path");
return -1;
}
std::string argv0AbsolutePath(path);
free(path);
std::string clrFilesAbsolutePath;
if(!GetClrFilesAbsolutePath(argv0AbsolutePath.c_str(), clrFilesPath, clrFilesAbsolutePath))
{
......
project(unixcoreruncommon)
set(CMAKE_INCLUDE_CURRENT_DIR ON)
include(configure.cmake)
_add_library(unixcoreruncommon
STATIC
coreruncommon.cpp
)
if(CLR_CMAKE_HOST_LINUX)
target_link_libraries(unixcoreruncommon dl)
endif(CLR_CMAKE_HOST_LINUX)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
//
// Code that is used by both the Unix corerun and coreconsole.
//
#include "config.h"
#include <cstdlib>
#include <cstring>
#include <assert.h>
#include <dirent.h>
#include <dlfcn.h>
#include <limits.h>
#include <set>
#include <string>
#include <string.h>
#include <sys/stat.h>
#if defined(__FreeBSD__)
#include <sys/types.h>
#include <sys/param.h>
#endif
#if HAVE_GETAUXVAL
#include <sys/auxv.h>
#endif
#if defined(HAVE_SYS_SYSCTL_H) || defined(__FreeBSD__)
#include <sys/sysctl.h>
#endif
#include "coreruncommon.h"
#include "coreclrhost.h"
#include <unistd.h>
#ifndef SUCCEEDED
#define SUCCEEDED(Status) ((Status) >= 0)
#endif // !SUCCEEDED
#if !HAVE_DIRENT_D_TYPE
#define DT_UNKNOWN 0
#define DT_DIR 4
#define DT_REG 8
#define DT_LNK 10
#endif
// Name of the environment variable controlling server GC.
// If set to 1, server GC is enabled on startup. If 0, server GC is
// disabled. Server GC is off by default.
static const char* serverGcVar = "COMPlus_gcServer";
// Name of environment variable to control "System.Globalization.Invariant"
// Set to 1 for Globalization Invariant mode to be true. Default is false.
static const char* globalizationInvariantVar = "CORECLR_GLOBAL_INVARIANT";
#if defined(__linux__)
#define symlinkEntrypointExecutable "/proc/self/exe"
#elif !defined(__APPLE__)
#define symlinkEntrypointExecutable "/proc/curproc/exe"
#endif
bool GetEntrypointExecutableAbsolutePath(std::string& entrypointExecutable)
{
bool result = false;
entrypointExecutable.clear();
// Get path to the executable for the current process using
// platform specific means.
#if defined(__APPLE__)
// On Mac, we ask the OS for the absolute path to the entrypoint executable
uint32_t lenActualPath = 0;
if (_NSGetExecutablePath(nullptr, &lenActualPath) == -1)
{
// OSX has placed the actual path length in lenActualPath,
// so re-attempt the operation
std::string resizedPath(lenActualPath, '\0');
char *pResizedPath = const_cast<char *>(resizedPath.c_str());
if (_NSGetExecutablePath(pResizedPath, &lenActualPath) == 0)
{
entrypointExecutable.assign(pResizedPath);
result = true;
}
}
#elif defined (__FreeBSD__)
static const int name[] = {
CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, -1
};
char path[PATH_MAX];
size_t len;
len = sizeof(path);
if (sysctl(name, 4, path, &len, nullptr, 0) == 0)
{
entrypointExecutable.assign(path);
result = true;
}
else
{
// ENOMEM
result = false;
}
#elif defined(__NetBSD__) && defined(KERN_PROC_PATHNAME)
static const int name[] = {
CTL_KERN, KERN_PROC_ARGS, -1, KERN_PROC_PATHNAME,
};
char path[MAXPATHLEN];
size_t len;
len = sizeof(path);
if (sysctl(name, __arraycount(name), path, &len, NULL, 0) != -1)
{
entrypointExecutable.assign(path);
result = true;
}
else
{
result = false;
}
#elif defined(__sun)
const char *path;
if ((path = getexecname()) == NULL)
{
result = false;
}
else if (*path != '/')
{
char *cwd;
if ((cwd = getcwd(NULL, PATH_MAX)) == NULL)
{
result = false;
}
else
{
entrypointExecutable
.assign(cwd)
.append("/")
.append(path);
result = true;
free(cwd);
}
}
else
{
entrypointExecutable.assign(path);
result = true;
}
#else
#if HAVE_GETAUXVAL && defined(AT_EXECFN)
const char *execfn = (const char *)getauxval(AT_EXECFN);
if (execfn)
{
entrypointExecutable.assign(execfn);
result = true;
}
else
#endif
// On other OSs, return the symlink that will be resolved by GetAbsolutePath
// to fetch the entrypoint EXE absolute path, inclusive of filename.
result = GetAbsolutePath(symlinkEntrypointExecutable, entrypointExecutable);
#endif
return result;
}
bool GetAbsolutePath(const char* path, std::string& absolutePath)
{
bool result = false;
char realPath[PATH_MAX];
if (realpath(path, realPath) != nullptr && realPath[0] != '\0')
{
absolutePath.assign(realPath);
// realpath should return canonicalized path without the trailing slash
assert(absolutePath.back() != '/');
result = true;
}
return result;
}
bool GetDirectory(const char* absolutePath, std::string& directory)
{
directory.assign(absolutePath);
size_t lastSlash = directory.rfind('/');
if (lastSlash != std::string::npos)
{
directory.erase(lastSlash);
return true;
}
return false;
}
bool GetClrFilesAbsolutePath(const char* currentExePath, const char* clrFilesPath, std::string& clrFilesAbsolutePath)
{
std::string clrFilesRelativePath;
const char* clrFilesPathLocal = clrFilesPath;
if (clrFilesPathLocal == nullptr)
{
// There was no CLR files path specified, use the folder of the corerun/coreconsole
if (!GetDirectory(currentExePath, clrFilesRelativePath))
{
perror("Failed to get directory from argv[0]");
return false;
}
clrFilesPathLocal = clrFilesRelativePath.c_str();
// TODO: consider using an env variable (if defined) as a fall-back.
// The windows version of the corerun uses core_root env variable
}
if (!GetAbsolutePath(clrFilesPathLocal, clrFilesAbsolutePath))
{
perror("Failed to convert CLR files path to absolute path");
return false;
}
return true;
}
void AddFilesFromDirectoryToTpaList(const char* directory, std::string& tpaList)
{
const char * const tpaExtensions[] = {
".ni.dll", // Probe for .ni.dll first so that it's preferred if ni and il coexist in the same dir
".dll",
".ni.exe",
".exe",
};
DIR* dir = opendir(directory);
if (dir == nullptr)
{
return;
}
std::set<std::string> addedAssemblies;
// Walk the directory for each extension separately so that we first get files with .ni.dll extension,
// then files with .dll extension, etc.
for (size_t extIndex = 0; extIndex < sizeof(tpaExtensions) / sizeof(tpaExtensions[0]); extIndex++)
{
const char* ext = tpaExtensions[extIndex];
int extLength = strlen(ext);
struct dirent* entry;
// For all entries in the directory
while ((entry = readdir(dir)) != nullptr)
{
#if HAVE_DIRENT_D_TYPE
int dirEntryType = entry->d_type;
#else
int dirEntryType = DT_UNKNOWN;
#endif
// We are interested in files only
switch (dirEntryType)
{
case DT_REG:
break;
// Handle symlinks and file systems that do not support d_type
case DT_LNK:
case DT_UNKNOWN:
{
std::string fullFilename;
fullFilename.append(directory);
fullFilename.append("/");
fullFilename.append(entry->d_name);
struct stat sb;
if (stat(fullFilename.c_str(), &sb) == -1)
{
continue;
}
if (!S_ISREG(sb.st_mode))
{
continue;
}
}
break;
default:
continue;
}
std::string filename(entry->d_name);
// Check if the extension matches the one we are looking for
int extPos = filename.length() - extLength;
if ((extPos <= 0) || (filename.compare(extPos, extLength, ext) != 0))
{
continue;
}
std::string filenameWithoutExt(filename.substr(0, extPos));
// Make sure if we have an assembly with multiple extensions present,
// we insert only one version of it.
if (addedAssemblies.find(filenameWithoutExt) == addedAssemblies.end())
{
addedAssemblies.insert(filenameWithoutExt);
tpaList.append(directory);
tpaList.append("/");
tpaList.append(filename);
tpaList.append(":");
}
}
// Rewind the directory stream to be able to iterate over it for the next extension
rewinddir(dir);
}
closedir(dir);
}
const char* GetEnvValueBoolean(const char* envVariable)
{
const char* envValue = std::getenv(envVariable);
if (envValue == nullptr)
{
envValue = "0";
}
// CoreCLR expects strings "true" and "false" instead of "1" and "0".
return (std::strcmp(envValue, "1") == 0 || strcasecmp(envValue, "true") == 0) ? "true" : "false";
}
static void *TryLoadHostPolicy(const char *hostPolicyPath)
{
#if defined(__APPLE__)
static const char LibrarySuffix[] = ".dylib";
#else // Various Linux-related OS-es
static const char LibrarySuffix[] = ".so";
#endif
std::string hostPolicyCompletePath(hostPolicyPath);
hostPolicyCompletePath.append(LibrarySuffix);
void *libraryPtr = dlopen(hostPolicyCompletePath.c_str(), RTLD_LAZY);
if (libraryPtr == nullptr)
{
fprintf(stderr, "Failed to load mock hostpolicy at path '%s'. Error: %s", hostPolicyCompletePath.c_str(), dlerror());
}
return libraryPtr;
}
int ExecuteManagedAssembly(
const char* currentExeAbsolutePath,
const char* clrFilesAbsolutePath,
const char* managedAssemblyAbsolutePath,
int managedAssemblyArgc,
const char** managedAssemblyArgv)
{
// Indicates failure
int exitCode = -1;
#ifdef HOST_ARM
// libunwind library is used to unwind stack frame, but libunwind for ARM
// does not support ARM vfpv3/NEON registers in DWARF format correctly.
// Therefore let's disable stack unwinding using DWARF information
// See https://github.com/dotnet/runtime/issues/6479
//
// libunwind use following methods to unwind stack frame.
// UNW_ARM_METHOD_ALL 0xFF
// UNW_ARM_METHOD_DWARF 0x01
// UNW_ARM_METHOD_FRAME 0x02
// UNW_ARM_METHOD_EXIDX 0x04
putenv(const_cast<char *>("UNW_ARM_UNWIND_METHOD=6"));
#endif // HOST_ARM
std::string coreClrDllPath(clrFilesAbsolutePath);
coreClrDllPath.append("/");
coreClrDllPath.append(coreClrDll);
if (coreClrDllPath.length() >= PATH_MAX)
{
fprintf(stderr, "Absolute path to libcoreclr.so too long\n");
return -1;
}
// Get just the path component of the managed assembly path
std::string appPath;
GetDirectory(managedAssemblyAbsolutePath, appPath);
std::string tpaList;
// Construct native search directory paths
std::string nativeDllSearchDirs(appPath);
char *coreLibraries = getenv("CORE_LIBRARIES");
if (coreLibraries)
{
nativeDllSearchDirs.append(":");
nativeDllSearchDirs.append(coreLibraries);
if (std::strcmp(coreLibraries, clrFilesAbsolutePath) != 0)
{
AddFilesFromDirectoryToTpaList(coreLibraries, tpaList);
}
}
nativeDllSearchDirs.append(":");
nativeDllSearchDirs.append(clrFilesAbsolutePath);
void* hostpolicyLib = nullptr;
char* mockHostpolicyPath = getenv("MOCK_HOSTPOLICY");
if (mockHostpolicyPath)
{
hostpolicyLib = TryLoadHostPolicy(mockHostpolicyPath);
if (hostpolicyLib == nullptr)
{
return -1;
}
}
AddFilesFromDirectoryToTpaList(clrFilesAbsolutePath, tpaList);
void* coreclrLib = dlopen(coreClrDllPath.c_str(), RTLD_NOW | RTLD_LOCAL);
if (coreclrLib != nullptr)
{
coreclr_initialize_ptr initializeCoreCLR = (coreclr_initialize_ptr)dlsym(coreclrLib, "coreclr_initialize");
coreclr_execute_assembly_ptr executeAssembly = (coreclr_execute_assembly_ptr)dlsym(coreclrLib, "coreclr_execute_assembly");
coreclr_shutdown_2_ptr shutdownCoreCLR = (coreclr_shutdown_2_ptr)dlsym(coreclrLib, "coreclr_shutdown_2");
if (initializeCoreCLR == nullptr)
{
fprintf(stderr, "Function coreclr_initialize not found in the libcoreclr.so\n");
}
else if (executeAssembly == nullptr)
{
fprintf(stderr, "Function coreclr_execute_assembly not found in the libcoreclr.so\n");
}
else if (shutdownCoreCLR == nullptr)
{
fprintf(stderr, "Function coreclr_shutdown_2 not found in the libcoreclr.so\n");
}
else
{
// Check whether we are enabling server GC (off by default)
const char* useServerGc = GetEnvValueBoolean(serverGcVar);
// Check Globalization Invariant mode (false by default)
const char* globalizationInvariant = GetEnvValueBoolean(globalizationInvariantVar);
// Allowed property names:
// APPBASE
// - The base path of the application from which the exe and other assemblies will be loaded
//
// TRUSTED_PLATFORM_ASSEMBLIES
// - The list of complete paths to each of the fully trusted assemblies
//
// APP_PATHS
// - The list of paths which will be probed by the assembly loader
//
// APP_NI_PATHS
// - The list of additional paths that the assembly loader will probe for ngen images
//
// NATIVE_DLL_SEARCH_DIRECTORIES
// - The list of paths that will be probed for native DLLs called by PInvoke
//
const char *propertyKeys[] = {
"TRUSTED_PLATFORM_ASSEMBLIES",
"APP_PATHS",
"APP_NI_PATHS",
"NATIVE_DLL_SEARCH_DIRECTORIES",
"System.GC.Server",
"System.Globalization.Invariant",
};
const char *propertyValues[] = {
// TRUSTED_PLATFORM_ASSEMBLIES
tpaList.c_str(),
// APP_PATHS
appPath.c_str(),
// APP_NI_PATHS
appPath.c_str(),
// NATIVE_DLL_SEARCH_DIRECTORIES
nativeDllSearchDirs.c_str(),
// System.GC.Server
useServerGc,
// System.Globalization.Invariant
globalizationInvariant,
};
void* hostHandle;
unsigned int domainId;
int st = initializeCoreCLR(
currentExeAbsolutePath,
"unixcorerun",
sizeof(propertyKeys) / sizeof(propertyKeys[0]),
propertyKeys,
propertyValues,
&hostHandle,
&domainId);
if (!SUCCEEDED(st))
{
fprintf(stderr, "coreclr_initialize failed - status: 0x%08x\n", st);
exitCode = -1;
}
else
{
st = executeAssembly(
hostHandle,
domainId,
managedAssemblyArgc,
managedAssemblyArgv,
managedAssemblyAbsolutePath,
(unsigned int*)&exitCode);
if (!SUCCEEDED(st))
{
fprintf(stderr, "coreclr_execute_assembly failed - status: 0x%08x\n", st);
exitCode = -1;
}
int latchedExitCode = 0;
st = shutdownCoreCLR(hostHandle, domainId, &latchedExitCode);
if (!SUCCEEDED(st))
{
fprintf(stderr, "coreclr_shutdown failed - status: 0x%08x\n", st);
exitCode = -1;
}
if (exitCode != -1)
{
exitCode = latchedExitCode;
}
}
}
}
else
{
const char* error = dlerror();
fprintf(stderr, "dlopen failed to open the libcoreclr.so with error %s\n", error);
}
if (hostpolicyLib)
{
if(dlclose(hostpolicyLib) != 0)
{
fprintf(stderr, "Warning - dlclose of mock hostpolicy failed.\n");
}
}
return exitCode;
}
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
#include <string>
// Get the path to entrypoint executable
bool GetEntrypointExecutableAbsolutePath(std::string& entrypointExecutable);
// Get absolute path from the specified path.
// Return true in case of a success, false otherwise.
bool GetAbsolutePath(const char* path, std::string& absolutePath);
// Get directory of the specified path.
// Return true in case of a success, false otherwise.
bool GetDirectory(const char* absolutePath, std::string& directory);
//
// Get the absolute path to use to locate libcoreclr.so and the CLR assemblies are stored. If clrFilesPath is provided,
// this function will return the absolute path to it. Otherwise, the directory of the current executable is used.
//
// Return true in case of a success, false otherwise.
//
bool GetClrFilesAbsolutePath(const char* currentExePath, const char* clrFilesPath, std::string& clrFilesAbsolutePath);
// Add all *.dll, *.ni.dll, *.exe, and *.ni.exe files from the specified directory to the tpaList string.
void AddFilesFromDirectoryToTpaList(const char* directory, std::string& tpaList);
//
// Execute the specified managed assembly.
//
// Parameters:
// currentExePath - Path to the current executable
// clrFilesAbsolutePath - Absolute path to the folder where the libcoreclr.so and CLR managed assemblies are stored
// managedAssemblyPath - Path to the managed assembly to execute
// managedAssemblyArgc - Number of arguments passed to the executed assembly
// managedAssemblyArgv - Array of arguments passed to the executed assembly
//
// Returns:
// ExitCode of the assembly
//
int ExecuteManagedAssembly(
const char* currentExeAbsolutePath,
const char* clrFilesAbsolutePath,
const char* managedAssemblyAbsolutePath,
int managedAssemblyArgc,
const char** managedAssemblyArgv);
#if defined(__APPLE__)
#include <mach-o/dyld.h>
static const char * const coreClrDll = "libcoreclr.dylib";
#else
static const char * const coreClrDll = "libcoreclr.so";
#endif
......@@ -117,6 +117,8 @@ if (CMAKE_CXX_COMPILER_ID MATCHES "GNU")
add_compile_options(-Wa,--divide)
endif()
include_directories("${CLR_SRC_NATIVE_DIR}/common")
set(SOURCES
cruntime/file.cpp
cruntime/filecrt.cpp
......
#ifndef _PAL_CONFIG_H_INCLUDED
#define _PAL_CONFIG_H_INCLUDED 1
#ifndef PAL_CONFIG_H_INCLUDED
#define PAL_CONFIG_H_INCLUDED
#cmakedefine01 HAVE_VM_FLAGS_SUPERPAGE_SIZE_ANY
#cmakedefine01 HAVE_MAP_HUGETLB
......@@ -170,4 +170,5 @@
#define SIGWAIT_FAILS_WHEN_PASSED_FULL_SIGSET 0
#define WRITE_0_BYTES_HANGS_TTY 0
#define HAVE_FTRUNCATE_LARGE_LENGTH_SUPPORT 1
#endif
#endif // PAL_CONFIG_H_INCLUDED
......@@ -3,8 +3,6 @@
/*++
Module Name:
init/pal.cpp
......@@ -13,8 +11,6 @@ Abstract:
Implementation of PAL exported functions not part of the Win32 API.
--*/
#include "pal/dbgmsg.h"
......@@ -43,6 +39,7 @@ SET_DEFAULT_DEBUG_CHANNEL(PAL); // some headers have code with asserts, so do th
#include "pal/numa.h"
#include "pal/stackstring.hpp"
#include "pal/cgroup.h"
#include <getexepath.h>
#if HAVE_MACH_EXCEPTIONS
#include "../exception/machexception.h"
......@@ -91,15 +88,6 @@ int CacheLineSize;
#endif
#endif
#if defined(__FreeBSD__)
#include <sys/types.h>
#include <sys/param.h>
#include <sys/sysctl.h>
#endif
#if HAVE_GETAUXVAL
#include <sys/auxv.h>
#endif
#include <algorithm>
using namespace CorUnix;
......@@ -378,7 +366,7 @@ Initialize(
gPID = getpid();
gSID = getsid(gPID);
// Initialize the thread local storage
// Initialize the thread local storage
if (FALSE == TLSInitialize())
{
palError = ERROR_PALINIT_TLS;
......@@ -1266,139 +1254,6 @@ static LPWSTR INIT_FormatCommandLine (int argc, const char * const *argv)
return retval;
}
#if defined(__linux__)
#define symlinkEntrypointExecutable "/proc/self/exe"
#elif !defined(__APPLE__)
#define symlinkEntrypointExecutable "/proc/curproc/exe"
#endif
bool GetAbsolutePath(const char* path, PathCharString& absolutePath)
{
bool result = false;
char realPath[PATH_MAX];
if (realpath(path, realPath) != nullptr && realPath[0] != '\0')
{
absolutePath.Set(realPath, strlen(realPath));
// realpath should return canonicalized path without the trailing slash
_ASSERTE(absolutePath[absolutePath.GetCount() - 1] != '/');
result = true;
}
return result;
}
bool GetEntrypointExecutableAbsolutePath(PathCharString& entrypointExecutable)
{
bool result = false;
entrypointExecutable.Clear();
// Get path to the executable for the current process using
// platform specific means.
#if defined(__APPLE__)
// On Mac, we ask the OS for the absolute path to the entrypoint executable
uint32_t lenActualPath = 0;
if (_NSGetExecutablePath(nullptr, &lenActualPath) == -1)
{
// OSX has placed the actual path length in lenActualPath,
// so re-attempt the operation
PathCharString resizedPath;
char *pResizedPath = resizedPath.OpenStringBuffer(lenActualPath);
if (_NSGetExecutablePath(pResizedPath, &lenActualPath) == 0)
{
resizedPath.CloseBuffer(lenActualPath - 1);
entrypointExecutable.Set(resizedPath);
result = true;
}
}
#elif defined (__FreeBSD__)
static const int name[] =
{
CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, -1
};
char path[PATH_MAX];
size_t len;
len = sizeof(path);
if (sysctl(name, 4, path, &len, nullptr, 0) == 0)
{
entrypointExecutable.Set(path, len);
result = true;
}
else
{
// ENOMEM
result = false;
}
#elif defined(__NetBSD__) && defined(KERN_PROC_PATHNAME)
static const int name[] =
{
CTL_KERN, KERN_PROC_ARGS, -1, KERN_PROC_PATHNAME,
};
char path[MAXPATHLEN];
size_t len;
len = sizeof(path);
if (sysctl(name, __arraycount(name), path, &len, NULL, 0) != -1)
{
entrypointExecutable.Set(path, len);
result = true;
}
else
{
result = false;
}
#elif defined(__sun)
const char *path;
if ((path = getexecname()) == NULL)
{
result = false;
}
else if (*path != '/')
{
char *cwd;
if ((cwd = getcwd(NULL, PATH_MAX)) == NULL)
{
result = false;
}
else
{
entrypointExecutable.Set(cwd, strlen(cwd));
entrypointExecutable.Append('/');
entrypointExecutable.Append(path, strlen(path));
result = true;
free(cwd);
}
}
else
{
entrypointExecutable.Set(path, strlen(path));
result = true;
}
#else
#if HAVE_GETAUXVAL && defined(AT_EXECFN)
const char *execfn = (const char *)getauxval(AT_EXECFN);
if (execfn)
{
entrypointExecutable.Set(execfn, strlen(execfn));
result = true;
}
else
#endif
// On other OSs, return the symlink that will be resolved by GetAbsolutePath
// to fetch the entrypoint EXE absolute path, inclusive of filename.
result = GetAbsolutePath(symlinkEntrypointExecutable, entrypointExecutable);
#endif
return result;
}
/*++
Function:
INIT_GetCurrentEXEPath
......@@ -1413,16 +1268,20 @@ Return:
--*/
static LPWSTR INIT_GetCurrentEXEPath()
{
PathCharString real_path;
LPWSTR return_value;
INT return_size;
if (!GetEntrypointExecutableAbsolutePath(real_path))
char* path = getexepath();
if (!path)
{
ERROR( "Cannot get current exe path\n" );
return NULL;
}
PathCharString real_path;
real_path.Set(path, strlen(path));
free(path);
return_size = MultiByteToWideChar(CP_ACP, 0, real_path, -1, NULL, 0);
if (0 == return_size)
{
......
......@@ -6,6 +6,7 @@ endif()
project(corehost)
include(../../../eng/native/configurepaths.cmake)
include(${CLR_ENG_NATIVE_DIR}/configurecompiler.cmake)
if(MSVC)
......
......@@ -154,9 +154,9 @@ echo "Computed RID for native build is %cm_BaseRid%"
set __ExtraCmakeParams=%__ExtraCmakeParams% "-DCLI_CMAKE_HOST_VER=%__HostVersion%" "-DCLI_CMAKE_COMMON_HOST_VER=%__AppHostVersion%" "-DCLI_CMAKE_HOST_FXR_VER=%__HostFxrVersion%"
set __ExtraCmakeParams=%__ExtraCmakeParams% "-DCLI_CMAKE_HOST_POLICY_VER=%__HostPolicyVersion%" "-DCLI_CMAKE_PKG_RID=%cm_BaseRid%" "-DCLI_CMAKE_COMMIT_HASH=%__CommitSha%"
set __ExtraCmakeParams=%__ExtraCmakeParams% "-DCORECLR_ARTIFACTS=%__CoreClrArtifacts% " "-DRUNTIME_CONFIG=%__RuntimeConfiguration%" "-DNATIVE_LIBS_ARTIFACTS=%__NativeLibsArtifacts%"
set __ExtraCmakeParams=%__ExtraCmakeParams% "-DCORECLR_ARTIFACTS=%__CoreClrArtifacts% " "-DRUNTIME_CONFIG=%__RuntimeConfiguration%" "-DNATIVE_LIBS_ARTIFACTS=%__NativeLibsArtifacts%"
set __ExtraCmakeParams=%__ExtraCmakeParams% "-DRUNTIME_FLAVOR=%__RuntimeFlavor% "
set __ExtraCmakeParams=%__ExtraCmakeParams% "-DCLI_CMAKE_RESOURCE_DIR=%__ResourcesDir%" "-DCLR_ENG_NATIVE_DIR=%__engNativeDir%" "-DCMAKE_BUILD_TYPE=%CMAKE_BUILD_TYPE%"
set __ExtraCmakeParams=%__ExtraCmakeParams% "-DCLI_CMAKE_RESOURCE_DIR=%__ResourcesDir%" "-DCMAKE_BUILD_TYPE=%CMAKE_BUILD_TYPE%"
:: Regenerate the native build files
echo Calling "%__engNativeDir%\gen-buildsys.cmd "%__sourceDir%" "%__IntermediatesDir%" %__VSVersion% %__BuildArch% %__ExtraCmakeParams%"
......
#ifndef _PAL_CONFIG_H_INCLUDED
#define _PAL_CONFIG_H_INCLUDED 1
#ifndef PAL_HOST_MISC_CONFIG_H_INCLUDED
#define PAL_HOST_MISC_CONFIG_H_INCLUDED
#cmakedefine01 HAVE_DIRENT_D_TYPE
#cmakedefine01 HAVE_GETAUXVAL
#endif
#endif // PAL_HOST_MISC_CONFIG_H_INCLUDED
include(CheckStructHasMember)
include(CheckSymbolExists)
check_struct_has_member("struct dirent" d_type dirent.h HAVE_DIRENT_D_TYPE)
configure_file(${CMAKE_CURRENT_LIST_DIR}/config.h.in ${CMAKE_CURRENT_BINARY_DIR}/config.h)
check_symbol_exists(getauxval sys/auxv.h HAVE_GETAUXVAL)
......@@ -3,6 +3,7 @@
include(${CMAKE_CURRENT_LIST_DIR}/configure.cmake)
include_directories(${CMAKE_CURRENT_BINARY_DIR})
include_directories("${CLR_SRC_NATIVE_DIR}/common")
if(CLR_CMAKE_TARGET_OS_ILLUMOS)
add_definitions(-DTARGET_ILLUMOS)
......
......@@ -5,6 +5,7 @@
#define _WITH_GETLINE
#endif
#include <getexepath.h>
#include "pal.h"
#include "utils.h"
#include "trace.h"
......@@ -28,12 +29,6 @@
#include <sys/utsname.h>
#endif
#if defined(TARGET_LINUX)
#define symlinkEntrypointExecutable "/proc/self/exe"
#elif !defined(TARGET_OSX)
#define symlinkEntrypointExecutable "/proc/curproc/exe"
#endif
#if !HAVE_DIRENT_D_TYPE
#define DT_UNKNOWN 0
#define DT_DIR 4
......@@ -793,90 +788,18 @@ pal::string_t pal::get_current_os_rid_platform()
}
#endif
#if defined(TARGET_OSX)
bool pal::get_own_executable_path(pal::string_t* recv)
{
uint32_t path_length = 0;
if (_NSGetExecutablePath(nullptr, &path_length) == -1)
{
char path_buf[path_length];
if (_NSGetExecutablePath(path_buf, &path_length) == 0)
{
recv->assign(path_buf);
return true;
}
}
return false;
}
#elif defined(TARGET_FREEBSD)
bool pal::get_own_executable_path(pal::string_t* recv)
{
int mib[4];
mib[0] = CTL_KERN;
mib[1] = KERN_PROC;
mib[2] = KERN_PROC_PATHNAME;
mib[3] = -1;
char buf[PATH_MAX];
size_t cb = sizeof(buf);
int error_code = 0;
error_code = sysctl(mib, 4, buf, &cb, NULL, 0);
if (error_code == 0)
{
recv->assign(buf);
return true;
}
// ENOMEM
if (error_code == ENOMEM)
{
size_t len = sysctl(mib, 4, NULL, NULL, NULL, 0);
std::unique_ptr<char[]> buffer (new (std::nothrow) char[len]);
if (buffer == NULL)
{
return false;
}
error_code = sysctl(mib, 4, buffer.get(), &len, NULL, 0);
if (error_code == 0)
{
recv->assign(buffer.get());
return true;
}
}
return false;
}
#elif defined(__sun)
bool pal::get_own_executable_path(pal::string_t* recv)
{
const char *path;
if ((path = getexecname()) == NULL)
char* path = getexepath();
if (!path)
{
return false;
}
else if (*path != '/')
{
if (!getcwd(recv))
{
return false;
}
recv->append("/").append(path);
return true;
}
recv->assign(path);
free(path);
return true;
}
#else
bool pal::get_own_executable_path(pal::string_t* recv)
{
// Just return the symlink to the exe from /proc
// We'll call realpath on it later
recv->assign(symlinkEntrypointExecutable);
return true;
}
#endif
bool pal::get_own_module_path(string_t* recv)
{
......
cmake_minimum_required(VERSION 3.6.2)
include(CheckCCompilerFlag)
if(CLR_CMAKE_TARGET_IOS OR CLR_CMAKE_TARGET_TVOS)
# CMake 3.14.5 contains bug fixes for iOS
cmake_minimum_required(VERSION 3.14.5)
endif()
if(CLR_CMAKE_TARGET_IOS OR CLR_CMAKE_TARGET_TVOS)
# CMake 3.14.5 contains bug fixes for iOS
cmake_minimum_required(VERSION 3.14.5)
endif()
cmake_policy(SET CMP0042 NEW)
project(CoreFX C)
include(../../../../eng/native/configurepaths.cmake)
include(${CLR_ENG_NATIVE_DIR}/configuretools.cmake)
set(CMAKE_MACOSX_RPATH ON)
if(CLR_CMAKE_TARGET_IOS OR CLR_CMAKE_TARGET_TVOS)
if(CLR_CMAKE_TARGET_IOS OR CLR_CMAKE_TARGET_TVOS)
set(CMAKE_BUILD_WITH_INSTALL_NAME_DIR ON)
set(CMAKE_INSTALL_NAME_DIR "@rpath")
endif()
......
......@@ -94,6 +94,7 @@
#cmakedefine01 HAVE_GSS_KRB5_CRED_NO_CI_FLAGS_X
#cmakedefine01 HAVE_HEIMDAL_HEADERS
#cmakedefine01 HAVE_NSGETENVIRON
#cmakedefine01 HAVE_GETAUXVAL
#cmakedefine01 HAVE_CRT_EXTERNS_H
#cmakedefine01 HAVE_GETDOMAINNAME
#cmakedefine01 HAVE_UNAME
......
......@@ -4,6 +4,8 @@ if (NOT CLR_CMAKE_TARGET_IOS AND NOT CLR_CMAKE_TARGET_TVOS)
add_definitions(-DHAS_CONSOLE_SIGNALS)
endif ()
include_directories("${CLR_SRC_NATIVE_DIR}/common")
set(NATIVE_SOURCES
pal_errno.c
pal_interfaceaddresses.c
......
......@@ -38,6 +38,8 @@
#include <sys/sysctl.h>
#endif
#include <getexepath.h>
// Validate that our SysLogPriority values are correct for the platform
c_static_assert(PAL_LOG_EMERG == LOG_EMERG);
c_static_assert(PAL_LOG_ALERT == LOG_ALERT);
......@@ -868,56 +870,7 @@ int32_t SystemNative_SchedGetAffinity(int32_t pid, intptr_t* mask)
}
#endif
// Returns the full path to the executable for the current process, resolving symbolic links.
// The caller is responsible for releasing the buffer. Returns null on error.
char* SystemNative_GetProcessPath()
{
#if defined(__APPLE__)
uint32_t path_length = 0;
if (_NSGetExecutablePath(NULL, &path_length) != -1)
{
errno = EINVAL;
return NULL;
}
char path_buf[path_length];
if (_NSGetExecutablePath(path_buf, &path_length) != 0)
{
errno = EINVAL;
return NULL;
}
return realpath(path_buf, NULL);
#elif defined(__FreeBSD__)
static const int name[] =
{
CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, -1
};
char path[PATH_MAX];
size_t len;
len = sizeof(path);
if (sysctl(name, 4, path, &len, NULL, 0) != 0)
{
return NULL;
}
return strdup(path);
#elif defined(__sun)
const char* path = getexecname();
if (path == NULL)
return NULL;
return realpath(path, NULL);
#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
return realpath(symlinkEntrypointExecutable, NULL);
#endif
return getexepath();
}
......@@ -938,6 +938,7 @@ else ()
HAVE_GSS_KRB5_CRED_NO_CI_FLAGS_X)
endif ()
check_symbol_exists(getauxval sys/auxv.h HAVE_GETAUXVAL)
check_include_files(crt_externs.h HAVE_CRT_EXTERNS_H)
if (HAVE_CRT_EXTERNS_H)
......
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
#ifndef GETEXEPATH_H
#define GETEXEPATH_H
#include <errno.h>
#include <limits.h>
#include <stdlib.h>
#if defined(__APPLE__)
#include <mach-o/dyld.h>
#elif defined(__FreeBSD__)
#include <string.h>
#include <sys/types.h>
#include <sys/param.h>
#include <sys/sysctl.h>
#endif
#ifdef __cplusplus
extern "C" {
#endif
// Returns the full path to the executable for the current process, resolving symbolic links.
// The caller is responsible for releasing the buffer. Returns null on error.
extern inline char* getexepath(void)
{
#if defined(__APPLE__)
uint32_t path_length = 0;
if (_NSGetExecutablePath(NULL, &path_length) != -1)
{
errno = EINVAL;
return NULL;
}
char path_buf[path_length];
if (_NSGetExecutablePath(path_buf, &path_length) != 0)
{
errno = EINVAL;
return NULL;
}
return realpath(path_buf, 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(__sun)
const char* path = getexecname();
if (path == NULL)
{
return NULL;
}
return realpath(path, NULL);
#else
#if HAVE_GETAUXVAL && defined(AT_EXECFN)
const char* path = (const char *)getauxval(AT_EXECFN);
if (path)
{
return realpath(path, NULL);
}
#endif // HAVE_GETAUXVAL && defined(AT_EXECFN)
#ifdef __linux__
const char* symlinkEntrypointExecutable = "/proc/self/exe";
#else
const char* symlinkEntrypointExecutable = "/proc/curproc/exe";
#endif
// Resolve the symlink to the executable from /proc
return realpath(symlinkEntrypointExecutable, NULL);
#endif // defined(__APPLE__)
}
#ifdef __cplusplus
}
#endif // extern "C"
#endif // GETEXEPATH_H
......@@ -6,6 +6,7 @@ if (CMAKE_VERSION VERSION_GREATER 3.15 OR CMAKE_VERSION VERSION_EQUAL 3.15)
endif()
project(Tests)
include(../../eng/native/configurepaths.cmake)
include(${CLR_ENG_NATIVE_DIR}/configurecompiler.cmake)
# Add this subdir. We install the headers for the jit.
......
......@@ -223,7 +223,7 @@ if not defined VSINSTALLDIR (
)
if not exist "%VSINSTALLDIR%DIA SDK" goto NoDIA
set __ExtraCmakeArgs="-DCMAKE_SYSTEM_VERSION=10.0" "-DCLR_ENG_NATIVE_DIR=%__RepoRootDir%/eng/native"
set __ExtraCmakeArgs="-DCMAKE_SYSTEM_VERSION=10.0"
call "%__RepoRootDir%\eng\native\gen-buildsys.cmd" "%__ProjectFilesDir%" "%__NativeTestIntermediatesDir%" %__VSVersion% %__BuildArch% !__ExtraCmakeArgs!
if not !errorlevel! == 0 (
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册