Files
RedHotRoast-ios/HybridCLRData/LocalIl2CppData-OSXEditor/il2cpp/libil2cpp/os/Posix/LibraryLoader.cpp
T
2026-07-17 14:03:00 +08:00

158 lines
5.8 KiB
C++

#include "il2cpp-config.h"
#if IL2CPP_TARGET_POSIX && !IL2CPP_USE_PLATFORM_SPECIFIC_LIBRARYLOADER
#include <dlfcn.h>
#include <string>
#include <set>
#if IL2CPP_TARGET_LINUX
#include <unistd.h>
#include <gnu/lib-names.h>
#endif
#include "il2cpp-runtime-metadata.h"
#include "os/LibraryLoader.h"
#include "utils/PathUtils.h"
#include "utils/StringUtils.h"
#include "utils/Environment.h"
namespace il2cpp
{
namespace os
{
struct LibraryNamePrefixAndSuffix
{
LibraryNamePrefixAndSuffix(const char* prefix_, const char* suffix_)
{
prefix = std::string(prefix_);
suffix = std::string(suffix_);
}
std::string prefix;
std::string suffix;
};
static LibraryNamePrefixAndSuffix LibraryNamePrefixAndSuffixVariations[8] =
{
LibraryNamePrefixAndSuffix("", ".so"),
LibraryNamePrefixAndSuffix("", ".dll"),
LibraryNamePrefixAndSuffix("", ".dylib"),
LibraryNamePrefixAndSuffix("", ".bundle"),
LibraryNamePrefixAndSuffix("lib", ".so"),
LibraryNamePrefixAndSuffix("lib", ".dll"),
LibraryNamePrefixAndSuffix("lib", ".dylib"),
LibraryNamePrefixAndSuffix("lib", ".bundle")
};
const HardcodedPInvokeDependencyLibrary* LibraryLoader::HardcodedPInvokeDependencies = NULL;
const size_t LibraryLoader::HardcodedPInvokeDependenciesCount = 0;
static Baselib_DynamicLibrary_Handle LoadLibraryWithName(const char* name, std::string& detailedError)
{
#if IL2CPP_TARGET_IOS
std::string dirName;
if (utils::Environment::GetNumMainArgs() > 0)
{
std::string main = utils::StringUtils::Utf16ToUtf8(utils::Environment::GetMainArgs()[0]);
dirName = utils::PathUtils::DirectoryName(main);
}
std::string libPath = utils::StringUtils::Printf("%s/%s", dirName.c_str(), name);
auto errorState = Baselib_ErrorState_Create();
auto handle = LibraryLoader::TryOpeningLibrary(libPath.c_str(), detailedError);
if (handle != Baselib_DynamicLibrary_Handle_Invalid)
return handle;
// Fallback to just using the name. This might be a system dylib.
return LibraryLoader::TryOpeningLibrary(name, detailedError);
#else
return LibraryLoader::TryOpeningLibrary(name, detailedError);
#endif
}
#if IL2CPP_TARGET_LINUX
static Baselib_DynamicLibrary_Handle LoadLibraryRelativeToExecutableDirectory(const char* name, std::string& detailedError)
{
if (name == NULL || name[0] == '/')
return Baselib_DynamicLibrary_Handle_Invalid;
char exePath[PATH_MAX + 1];
int len;
if ((len = readlink("/proc/self/exe", exePath, sizeof(exePath))) == -1)
{
return Baselib_DynamicLibrary_Handle_Invalid;
}
exePath[len] = '\0'; // readlink does not terminate buffer
while (len > 0 && exePath[len] != '/')
len--;
exePath[len] = '\0';
std::string libPath = utils::StringUtils::Printf("%s/%s", exePath, name);
return LibraryLoader::TryOpeningLibrary(libPath.c_str(), detailedError);
}
#endif
static Baselib_DynamicLibrary_Handle CheckLibraryVariations(const char* name, std::string& detailedError)
{
const int numberOfVariations = sizeof(LibraryNamePrefixAndSuffixVariations) / sizeof(LibraryNamePrefixAndSuffixVariations[0]);
for (int i = 0; i < numberOfVariations; ++i)
{
std::string libraryName = LibraryNamePrefixAndSuffixVariations[i].prefix + name + LibraryNamePrefixAndSuffixVariations[i].suffix;
auto handle = LoadLibraryWithName(libraryName.c_str(), detailedError);
if (handle != Baselib_DynamicLibrary_Handle_Invalid)
return handle;
#if IL2CPP_TARGET_LINUX
// Linux does not search current directory by default
handle = LoadLibraryRelativeToExecutableDirectory(libraryName.c_str(), detailedError);
if (handle != Baselib_DynamicLibrary_Handle_Invalid)
return handle;
#endif
}
return Baselib_DynamicLibrary_Handle_Invalid;
}
Baselib_DynamicLibrary_Handle LibraryLoader::ProbeForLibrary(const Il2CppNativeChar* libraryName, const size_t libraryNameLength, std::string& detailedError)
{
auto handle = Baselib_DynamicLibrary_Handle_Invalid;
#if IL2CPP_TARGET_LINUX
// Workaround the fact that on Linux, libc is actually named libc.so.6 instead of libc.so.
// mscorlib P/Invokes into plain libc, so we need this for those P/Invokes to succeed
if (strncasecmp(libraryName, "libc", libraryNameLength) == 0)
handle = LoadLibraryWithName(LIBC_SO, detailedError);
#endif
if (handle == Baselib_DynamicLibrary_Handle_Invalid)
handle = LoadLibraryWithName(libraryName, detailedError);
if (handle == Baselib_DynamicLibrary_Handle_Invalid)
handle = CheckLibraryVariations(libraryName, detailedError);
if (handle == Baselib_DynamicLibrary_Handle_Invalid)
{
const size_t lengthWithoutDotDll = libraryNameLength - 4;
if (strncmp(libraryName + lengthWithoutDotDll, ".dll", 4) == 0)
{
char* nativeDynamicLibraryWithoutExtension = static_cast<char*>(alloca((lengthWithoutDotDll + 1) * sizeof(char)));
memcpy(nativeDynamicLibraryWithoutExtension, libraryName, lengthWithoutDotDll);
nativeDynamicLibraryWithoutExtension[lengthWithoutDotDll] = 0;
handle = CheckLibraryVariations(nativeDynamicLibraryWithoutExtension, detailedError);
}
}
return handle;
}
Baselib_DynamicLibrary_Handle LibraryLoader::OpenProgramHandle(Baselib_ErrorState& errorState, bool& /*needsClosing*/)
{
return Baselib_DynamicLibrary_OpenProgramHandle(&errorState);
}
}
}
#endif