123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294 |
- #include "LibraryLoader.h"
- #include "utils/StringUtils.h"
- #include "utils/Exception.h"
- #if !RUNTIME_TINY
- #include "os/Mutex.h"
- #endif
- namespace il2cpp
- {
- namespace os
- {
- static Il2CppSetFindPlugInCallback s_FindPluginCallback = NULL;
- #if !RUNTIME_TINY
- typedef std::vector<std::pair<std::basic_string<Il2CppNativeChar>, Baselib_DynamicLibrary_Handle> > DllCacheContainer;
- typedef DllCacheContainer::const_iterator DllCacheIterator;
- static DllCacheContainer s_DllCache;
- static baselib::ReentrantLock s_DllCacheMutex;
- #endif
- static inline Il2CppNativeChar AsciiToLower(Il2CppNativeChar c)
- {
- if (c >= 'A' && c <= 'Z')
- return c - 'A' + 'a';
- return c;
- }
- static bool DoesNativeDynamicLibraryNameMatch(const il2cpp::utils::StringView<Il2CppNativeChar>& desiredLibraryName, const Il2CppNativeChar* hardcodedLibraryName)
- {
- size_t desiredLibraryNameLength = desiredLibraryName.Length();
- for (size_t i = 0; i < desiredLibraryNameLength; i++)
- {
- Il2CppNativeChar desiredCharacter = AsciiToLower(desiredLibraryName[i]);
- Il2CppNativeChar hardcodedCharacter = hardcodedLibraryName[i];
-
- IL2CPP_ASSERT(hardcodedCharacter < 128 && (hardcodedCharacter<'A' || hardcodedCharacter> 'Z'));
- if (desiredCharacter != hardcodedCharacter)
- {
-
-
- return hardcodedCharacter == 0 &&
- i + 4 == desiredLibraryNameLength &&
- desiredLibraryName[i] == '.' &&
- AsciiToLower(desiredLibraryName[i + 1]) == 'd' &&
- AsciiToLower(desiredLibraryName[i + 2]) == 'l' &&
- AsciiToLower(desiredLibraryName[i + 3]) == 'l';
- }
- else if (hardcodedCharacter == 0)
- {
-
-
- return i + 1 == desiredLibraryNameLength;
- }
- else if (i == desiredLibraryNameLength - 1)
- {
-
-
- return hardcodedLibraryName[i + 1] == 0;
- }
- }
-
-
-
- return false;
- }
- Il2CppMethodPointer LibraryLoader::GetHardcodedPInvokeDependencyFunctionPointer(const il2cpp::utils::StringView<Il2CppNativeChar>& nativeDynamicLibrary, const il2cpp::utils::StringView<char>& entryPoint, Il2CppCharSet charSet)
- {
-
- if (HardcodedPInvokeDependencies == NULL || charSet == CHARSET_ANSI)
- return NULL;
- for (size_t i = 0; i < HardcodedPInvokeDependenciesCount; i++)
- {
- const HardcodedPInvokeDependencyLibrary& library = HardcodedPInvokeDependencies[i];
- if (DoesNativeDynamicLibraryNameMatch(nativeDynamicLibrary, library.libraryName))
- {
- size_t functionCount = library.functionCount;
- for (size_t j = 0; j < functionCount; j++)
- {
- const HardcodedPInvokeDependencyFunction function = library.functions[j];
- if (EntryNameMatches(il2cpp::utils::StringView<char>(function.functionName, function.functionNameLen), entryPoint))
- return function.functionPointer;
- }
-
- return NULL;
- }
- }
- return NULL;
- }
- Baselib_DynamicLibrary_Handle LibraryLoader::LoadDynamicLibrary(const utils::StringView<Il2CppNativeChar> nativeDynamicLibrary, std::string& detailedError)
- {
- StringViewAsNullTerminatedStringOf(Il2CppNativeChar, nativeDynamicLibrary, libraryName);
- if (s_FindPluginCallback)
- libraryName = s_FindPluginCallback(libraryName);
- auto libraryNameLength = utils::StringUtils::StrLen(libraryName);
- #if !RUNTIME_TINY
- {
- os::FastAutoLock lock(&s_DllCacheMutex);
- for (DllCacheIterator it = s_DllCache.begin(); it != s_DllCache.end(); it++)
- if (it->first.compare(0, std::string::npos, libraryName, libraryNameLength) == 0)
- return it->second;
- }
- #endif
- bool needsClosing = true;
- auto handle = Baselib_DynamicLibrary_Handle_Invalid;
- if (libraryName == nullptr || libraryNameLength == 0)
- {
- auto errorState = Baselib_ErrorState_Create();
- handle = OpenProgramHandle(errorState, needsClosing);
-
- #if (!RUNTIME_TINY) && (!defined(__EMSCRIPTEN__))
- if (Baselib_ErrorState_ErrorRaised(&errorState))
- {
- if (!detailedError.empty())
- detailedError += " ";
- detailedError += "Unable to open program handle because of '";
- detailedError += utils::Exception::FormatBaselibErrorState(errorState);
- detailedError += "'.";
- }
- #endif
- }
- else
- handle = ProbeForLibrary(libraryName, libraryNameLength, detailedError);
- #if !RUNTIME_TINY
- if ((handle != Baselib_DynamicLibrary_Handle_Invalid) && needsClosing)
- {
- os::FastAutoLock lock(&s_DllCacheMutex);
- s_DllCache.push_back(std::make_pair(libraryName, handle));
- }
- #endif
- return handle;
- }
- Il2CppMethodPointer LibraryLoader::GetFunctionPointer(Baselib_DynamicLibrary_Handle handle, const PInvokeArguments& pinvokeArgs, std::string& detailedError)
- {
- if (handle == Baselib_DynamicLibrary_Handle_Invalid)
- return NULL;
- StringViewAsNullTerminatedStringOf(char, pinvokeArgs.entryPoint, entryPoint);
-
- if (pinvokeArgs.isNoMangle)
- return GetFunctionPointer(handle, entryPoint, detailedError);
- const size_t kBufferOverhead = 10;
- Il2CppMethodPointer func = nullptr;
- size_t originalFuncNameLength = strlen(entryPoint) + 1;
- std::string functionName;
- functionName.resize(originalFuncNameLength + kBufferOverhead + 1);
- memcpy(&functionName[1], entryPoint, originalFuncNameLength);
- memset(&functionName[1] + originalFuncNameLength, 0, kBufferOverhead);
-
- if (pinvokeArgs.charSet == CHARSET_UNICODE)
- {
- functionName[originalFuncNameLength] = 'W';
- if ((func = GetFunctionPointer(handle, functionName.c_str() + 1, detailedError)))
- return func;
-
- if ((func = GetFunctionPointer(handle, entryPoint, detailedError)))
- return func;
- }
- else
- {
- if ((func = GetFunctionPointer(handle, entryPoint, detailedError)))
- return func;
-
- functionName[originalFuncNameLength] = 'A';
- if ((func = GetFunctionPointer(handle, functionName.c_str() + 1, detailedError)))
- return func;
- }
-
-
-
- #if defined(_X86_) && PLATFORM_ARCH_32
- if (sizeof(void*) == 4 && pinvokeArgs.callingConvention != IL2CPP_CALL_C)
- {
- functionName[0] = '_';
- sprintf(&functionName[0] + originalFuncNameLength, "@%i", pinvokeArgs.parameterSize);
- if ((func = GetFunctionPointer(handle, functionName.c_str(), detailedError)))
- return func;
- }
- #endif
- return NULL;
- }
- Il2CppMethodPointer LibraryLoader::GetFunctionPointer(Baselib_DynamicLibrary_Handle handle, const char* functionName, std::string& detailedError)
- {
- auto errorState = Baselib_ErrorState_Create();
- if (handle == Baselib_DynamicLibrary_Handle_Invalid)
- return NULL;
- auto func = reinterpret_cast<Il2CppMethodPointer>(Baselib_DynamicLibrary_GetFunction(handle, functionName, &errorState));
- #if (!RUNTIME_TINY) && (!defined(__EMSCRIPTEN__))
- if (Baselib_ErrorState_ErrorRaised(&errorState))
- {
- if (!detailedError.empty())
- detailedError += " ";
- detailedError += "Unable to get function '";
- detailedError += functionName;
- detailedError += "' because of '";
- detailedError += utils::Exception::FormatBaselibErrorState(errorState);
- detailedError += "'.";
- }
- #else
- NO_UNUSED_WARNING(detailedError);
- #endif
- return func;
- }
- void LibraryLoader::CleanupLoadedLibraries()
- {
- #if !RUNTIME_TINY
-
- for (DllCacheIterator it = s_DllCache.begin(); it != s_DllCache.end(); it++)
- {
-
-
-
-
- if (utils::StringUtils::NativeStringToUtf8(it->first.c_str()) != "libc")
- Baselib_DynamicLibrary_Close(it->second);
- }
- s_DllCache.clear();
- #endif
- }
- bool LibraryLoader::CloseLoadedLibrary(Baselib_DynamicLibrary_Handle handle)
- {
- if (handle == Baselib_DynamicLibrary_Handle_Invalid)
- return false;
- #if !RUNTIME_TINY
- os::FastAutoLock lock(&s_DllCacheMutex);
-
- for (DllCacheIterator it = s_DllCache.begin(); it != s_DllCache.end(); it++)
- {
- if (it->second == handle)
- {
- Baselib_DynamicLibrary_Close(it->second);
- s_DllCache.erase(it);
- return true;
- }
- }
- #endif
- return false;
- }
- void LibraryLoader::SetFindPluginCallback(Il2CppSetFindPlugInCallback method)
- {
- s_FindPluginCallback = method;
- }
- Baselib_DynamicLibrary_Handle LibraryLoader::TryOpeningLibrary(const Il2CppNativeChar* libraryName, std::string& detailedError)
- {
- auto errorState = Baselib_ErrorState_Create();
- auto handle = Baselib_DynamicLibrary_Open(utils::StringUtils::NativeStringToBaselib(libraryName), &errorState);
- #if (!RUNTIME_TINY) && (!defined(__EMSCRIPTEN__))
- if (Baselib_ErrorState_ErrorRaised(&errorState))
- {
- if (!detailedError.empty())
- detailedError += " ";
- detailedError += "Unable to load dynamic library '";
- detailedError += utils::StringUtils::NativeStringToUtf8(libraryName);
- detailedError += "' because of '";
- detailedError += utils::Exception::FormatBaselibErrorState(errorState);
- detailedError += "'.";
- }
- #else
- NO_UNUSED_WARNING(detailedError);
- #endif
- return handle;
- }
- }
- }
|