暂无描述
您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

LibraryLoader.cpp 5.8KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157
  1. #include "il2cpp-config.h"
  2. #if IL2CPP_TARGET_POSIX && !IL2CPP_USE_PLATFORM_SPECIFIC_LIBRARYLOADER
  3. #include <dlfcn.h>
  4. #include <string>
  5. #include <set>
  6. #if IL2CPP_TARGET_LINUX
  7. #include <unistd.h>
  8. #include <gnu/lib-names.h>
  9. #endif
  10. #include "il2cpp-runtime-metadata.h"
  11. #include "os/LibraryLoader.h"
  12. #include "utils/PathUtils.h"
  13. #include "utils/StringUtils.h"
  14. #include "utils/Environment.h"
  15. namespace il2cpp
  16. {
  17. namespace os
  18. {
  19. struct LibraryNamePrefixAndSuffix
  20. {
  21. LibraryNamePrefixAndSuffix(const char* prefix_, const char* suffix_)
  22. {
  23. prefix = std::string(prefix_);
  24. suffix = std::string(suffix_);
  25. }
  26. std::string prefix;
  27. std::string suffix;
  28. };
  29. static LibraryNamePrefixAndSuffix LibraryNamePrefixAndSuffixVariations[8] =
  30. {
  31. LibraryNamePrefixAndSuffix("", ".so"),
  32. LibraryNamePrefixAndSuffix("", ".dll"),
  33. LibraryNamePrefixAndSuffix("", ".dylib"),
  34. LibraryNamePrefixAndSuffix("", ".bundle"),
  35. LibraryNamePrefixAndSuffix("lib", ".so"),
  36. LibraryNamePrefixAndSuffix("lib", ".dll"),
  37. LibraryNamePrefixAndSuffix("lib", ".dylib"),
  38. LibraryNamePrefixAndSuffix("lib", ".bundle")
  39. };
  40. const HardcodedPInvokeDependencyLibrary* LibraryLoader::HardcodedPInvokeDependencies = NULL;
  41. const size_t LibraryLoader::HardcodedPInvokeDependenciesCount = 0;
  42. static Baselib_DynamicLibrary_Handle LoadLibraryWithName(const char* name, std::string& detailedError)
  43. {
  44. #if IL2CPP_TARGET_IOS
  45. std::string dirName;
  46. if (utils::Environment::GetNumMainArgs() > 0)
  47. {
  48. std::string main = utils::StringUtils::Utf16ToUtf8(utils::Environment::GetMainArgs()[0]);
  49. dirName = utils::PathUtils::DirectoryName(main);
  50. }
  51. std::string libPath = utils::StringUtils::Printf("%s/%s", dirName.c_str(), name);
  52. auto errorState = Baselib_ErrorState_Create();
  53. auto handle = LibraryLoader::TryOpeningLibrary(libPath.c_str(), detailedError);
  54. if (handle != Baselib_DynamicLibrary_Handle_Invalid)
  55. return handle;
  56. // Fallback to just using the name. This might be a system dylib.
  57. return LibraryLoader::TryOpeningLibrary(name, detailedError);
  58. #else
  59. return LibraryLoader::TryOpeningLibrary(name, detailedError);
  60. #endif
  61. }
  62. #if IL2CPP_TARGET_LINUX
  63. static Baselib_DynamicLibrary_Handle LoadLibraryRelativeToExecutableDirectory(const char* name, std::string& detailedError)
  64. {
  65. if (name == NULL || name[0] == '/')
  66. return Baselib_DynamicLibrary_Handle_Invalid;
  67. char exePath[PATH_MAX + 1];
  68. int len;
  69. if ((len = readlink("/proc/self/exe", exePath, sizeof(exePath))) == -1)
  70. {
  71. return Baselib_DynamicLibrary_Handle_Invalid;
  72. }
  73. exePath[len] = '\0'; // readlink does not terminate buffer
  74. while (len > 0 && exePath[len] != '/')
  75. len--;
  76. exePath[len] = '\0';
  77. std::string libPath = utils::StringUtils::Printf("%s/%s", exePath, name);
  78. return LibraryLoader::TryOpeningLibrary(libPath.c_str(), detailedError);
  79. }
  80. #endif
  81. static Baselib_DynamicLibrary_Handle CheckLibraryVariations(const char* name, std::string& detailedError)
  82. {
  83. const int numberOfVariations = sizeof(LibraryNamePrefixAndSuffixVariations) / sizeof(LibraryNamePrefixAndSuffixVariations[0]);
  84. for (int i = 0; i < numberOfVariations; ++i)
  85. {
  86. std::string libraryName = LibraryNamePrefixAndSuffixVariations[i].prefix + name + LibraryNamePrefixAndSuffixVariations[i].suffix;
  87. auto handle = LoadLibraryWithName(libraryName.c_str(), detailedError);
  88. if (handle != Baselib_DynamicLibrary_Handle_Invalid)
  89. return handle;
  90. #if IL2CPP_TARGET_LINUX
  91. // Linux does not search current directory by default
  92. handle = LoadLibraryRelativeToExecutableDirectory(libraryName.c_str(), detailedError);
  93. if (handle != Baselib_DynamicLibrary_Handle_Invalid)
  94. return handle;
  95. #endif
  96. }
  97. return Baselib_DynamicLibrary_Handle_Invalid;
  98. }
  99. Baselib_DynamicLibrary_Handle LibraryLoader::ProbeForLibrary(const Il2CppNativeChar* libraryName, const size_t libraryNameLength, std::string& detailedError)
  100. {
  101. auto handle = Baselib_DynamicLibrary_Handle_Invalid;
  102. #if IL2CPP_TARGET_LINUX
  103. // Workaround the fact that on Linux, libc is actually named libc.so.6 instead of libc.so.
  104. // mscorlib P/Invokes into plain libc, so we need this for those P/Invokes to succeed
  105. if (strncasecmp(libraryName, "libc", libraryNameLength) == 0)
  106. handle = LoadLibraryWithName(LIBC_SO, detailedError);
  107. #endif
  108. if (handle == Baselib_DynamicLibrary_Handle_Invalid)
  109. handle = LoadLibraryWithName(libraryName, detailedError);
  110. if (handle == Baselib_DynamicLibrary_Handle_Invalid)
  111. handle = CheckLibraryVariations(libraryName, detailedError);
  112. if (handle == Baselib_DynamicLibrary_Handle_Invalid)
  113. {
  114. const size_t lengthWithoutDotDll = libraryNameLength - 4;
  115. if (strncmp(libraryName + lengthWithoutDotDll, ".dll", 4) == 0)
  116. {
  117. char* nativeDynamicLibraryWithoutExtension = static_cast<char*>(alloca((lengthWithoutDotDll + 1) * sizeof(char)));
  118. memcpy(nativeDynamicLibraryWithoutExtension, libraryName, lengthWithoutDotDll);
  119. nativeDynamicLibraryWithoutExtension[lengthWithoutDotDll] = 0;
  120. handle = CheckLibraryVariations(nativeDynamicLibraryWithoutExtension, detailedError);
  121. }
  122. }
  123. return handle;
  124. }
  125. Baselib_DynamicLibrary_Handle LibraryLoader::OpenProgramHandle(Baselib_ErrorState& errorState, bool& /*needsClosing*/)
  126. {
  127. return Baselib_DynamicLibrary_OpenProgramHandle(&errorState);
  128. }
  129. }
  130. }
  131. #endif