COFFVCRuntimeSupport.cpp 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184
  1. //===------- COFFVCRuntimeSupport.cpp - VC runtime support in ORC ---------===//
  2. //
  3. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  4. // See https://llvm.org/LICENSE.txt for license information.
  5. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  6. //
  7. //===----------------------------------------------------------------------===//
  8. #include "llvm/ExecutionEngine/Orc/COFFVCRuntimeSupport.h"
  9. #include "llvm/ExecutionEngine/Orc/ExecutionUtils.h"
  10. #include "llvm/ExecutionEngine/Orc/LookupAndRecordAddrs.h"
  11. #include "llvm/Support/VirtualFileSystem.h"
  12. #include "llvm/WindowsDriver/MSVCPaths.h"
  13. #define DEBUG_TYPE "orc"
  14. using namespace llvm;
  15. using namespace llvm::orc;
  16. using namespace llvm::orc::shared;
  17. Expected<std::unique_ptr<COFFVCRuntimeBootstrapper>>
  18. COFFVCRuntimeBootstrapper::Create(ExecutionSession &ES,
  19. ObjectLinkingLayer &ObjLinkingLayer,
  20. const char *RuntimePath) {
  21. return std::unique_ptr<COFFVCRuntimeBootstrapper>(
  22. new COFFVCRuntimeBootstrapper(ES, ObjLinkingLayer, RuntimePath));
  23. }
  24. COFFVCRuntimeBootstrapper::COFFVCRuntimeBootstrapper(
  25. ExecutionSession &ES, ObjectLinkingLayer &ObjLinkingLayer,
  26. const char *RuntimePath)
  27. : ES(ES), ObjLinkingLayer(ObjLinkingLayer) {
  28. if (RuntimePath)
  29. this->RuntimePath = RuntimePath;
  30. }
  31. Expected<std::vector<std::string>>
  32. COFFVCRuntimeBootstrapper::loadStaticVCRuntime(JITDylib &JD,
  33. bool DebugVersion) {
  34. StringRef VCLibs[] = {"libvcruntime.lib", "libcmt.lib", "libcpmt.lib"};
  35. StringRef UCRTLibs[] = {"libucrt.lib"};
  36. std::vector<std::string> ImportedLibraries;
  37. if (auto Err = loadVCRuntime(JD, ImportedLibraries, ArrayRef(VCLibs),
  38. ArrayRef(UCRTLibs)))
  39. return std::move(Err);
  40. return ImportedLibraries;
  41. }
  42. Expected<std::vector<std::string>>
  43. COFFVCRuntimeBootstrapper::loadDynamicVCRuntime(JITDylib &JD,
  44. bool DebugVersion) {
  45. StringRef VCLibs[] = {"vcruntime.lib", "msvcrt.lib", "msvcprt.lib"};
  46. StringRef UCRTLibs[] = {"ucrt.lib"};
  47. std::vector<std::string> ImportedLibraries;
  48. if (auto Err = loadVCRuntime(JD, ImportedLibraries, ArrayRef(VCLibs),
  49. ArrayRef(UCRTLibs)))
  50. return std::move(Err);
  51. return ImportedLibraries;
  52. }
  53. Error COFFVCRuntimeBootstrapper::loadVCRuntime(
  54. JITDylib &JD, std::vector<std::string> &ImportedLibraries,
  55. ArrayRef<StringRef> VCLibs, ArrayRef<StringRef> UCRTLibs) {
  56. MSVCToolchainPath Path;
  57. if (!RuntimePath.empty()) {
  58. Path.UCRTSdkLib = RuntimePath;
  59. Path.VCToolchainLib = RuntimePath;
  60. } else {
  61. auto ToolchainPath = getMSVCToolchainPath();
  62. if (!ToolchainPath)
  63. return ToolchainPath.takeError();
  64. Path = *ToolchainPath;
  65. }
  66. LLVM_DEBUG({
  67. dbgs() << "Using VC toolchain pathes\n";
  68. dbgs() << " VC toolchain path: " << Path.VCToolchainLib << "\n";
  69. dbgs() << " UCRT path: " << Path.UCRTSdkLib << "\n";
  70. });
  71. auto LoadLibrary = [&](SmallString<256> LibPath, StringRef LibName) -> Error {
  72. sys::path::append(LibPath, LibName);
  73. auto G = StaticLibraryDefinitionGenerator::Load(ObjLinkingLayer,
  74. LibPath.c_str());
  75. if (!G)
  76. return G.takeError();
  77. for (auto &Lib : (*G)->getImportedDynamicLibraries())
  78. ImportedLibraries.push_back(Lib);
  79. JD.addGenerator(std::move(*G));
  80. return Error::success();
  81. };
  82. for (auto &Lib : UCRTLibs)
  83. if (auto Err = LoadLibrary(Path.UCRTSdkLib, Lib))
  84. return Err;
  85. for (auto &Lib : VCLibs)
  86. if (auto Err = LoadLibrary(Path.VCToolchainLib, Lib))
  87. return Err;
  88. ImportedLibraries.push_back("ntdll.dll");
  89. ImportedLibraries.push_back("Kernel32.dll");
  90. return Error::success();
  91. }
  92. Error COFFVCRuntimeBootstrapper::initializeStaticVCRuntime(JITDylib &JD) {
  93. ExecutorAddr jit_scrt_initialize, jit_scrt_dllmain_before_initialize_c,
  94. jit_scrt_initialize_type_info,
  95. jit_scrt_initialize_default_local_stdio_options;
  96. if (auto Err = lookupAndRecordAddrs(
  97. ES, LookupKind::Static, makeJITDylibSearchOrder(&JD),
  98. {{ES.intern("__scrt_initialize_crt"), &jit_scrt_initialize},
  99. {ES.intern("__scrt_dllmain_before_initialize_c"),
  100. &jit_scrt_dllmain_before_initialize_c},
  101. {ES.intern("?__scrt_initialize_type_info@@YAXXZ"),
  102. &jit_scrt_initialize_type_info},
  103. {ES.intern("__scrt_initialize_default_local_stdio_options"),
  104. &jit_scrt_initialize_default_local_stdio_options}}))
  105. return Err;
  106. auto RunVoidInitFunc = [&](ExecutorAddr Addr) -> Error {
  107. if (auto Res = ES.getExecutorProcessControl().runAsVoidFunction(Addr))
  108. return Error::success();
  109. else
  110. return Res.takeError();
  111. };
  112. auto R =
  113. ES.getExecutorProcessControl().runAsIntFunction(jit_scrt_initialize, 0);
  114. if (!R)
  115. return R.takeError();
  116. if (auto Err = RunVoidInitFunc(jit_scrt_dllmain_before_initialize_c))
  117. return Err;
  118. if (auto Err = RunVoidInitFunc(jit_scrt_initialize_type_info))
  119. return Err;
  120. if (auto Err =
  121. RunVoidInitFunc(jit_scrt_initialize_default_local_stdio_options))
  122. return Err;
  123. SymbolAliasMap Alias;
  124. Alias[ES.intern("__run_after_c_init")] = {
  125. ES.intern("__scrt_dllmain_after_initialize_c"), JITSymbolFlags::Exported};
  126. if (auto Err = JD.define(symbolAliases(Alias)))
  127. return Err;
  128. return Error::success();
  129. }
  130. Expected<COFFVCRuntimeBootstrapper::MSVCToolchainPath>
  131. COFFVCRuntimeBootstrapper::getMSVCToolchainPath() {
  132. std::string VCToolChainPath;
  133. ToolsetLayout VSLayout;
  134. IntrusiveRefCntPtr<vfs::FileSystem> VFS = vfs::getRealFileSystem();
  135. if (!findVCToolChainViaCommandLine(*VFS, std::nullopt, std::nullopt,
  136. std::nullopt, VCToolChainPath, VSLayout) &&
  137. !findVCToolChainViaEnvironment(*VFS, VCToolChainPath, VSLayout) &&
  138. !findVCToolChainViaSetupConfig(*VFS, VCToolChainPath, VSLayout) &&
  139. !findVCToolChainViaRegistry(VCToolChainPath, VSLayout))
  140. return make_error<StringError>("Couldn't find msvc toolchain.",
  141. inconvertibleErrorCode());
  142. std::string UniversalCRTSdkPath;
  143. std::string UCRTVersion;
  144. if (!getUniversalCRTSdkDir(*VFS, std::nullopt, std::nullopt, std::nullopt,
  145. UniversalCRTSdkPath, UCRTVersion))
  146. return make_error<StringError>("Couldn't find universal sdk.",
  147. inconvertibleErrorCode());
  148. MSVCToolchainPath ToolchainPath;
  149. SmallString<256> VCToolchainLib(VCToolChainPath);
  150. sys::path::append(VCToolchainLib, "lib", "x64");
  151. ToolchainPath.VCToolchainLib = VCToolchainLib;
  152. SmallString<256> UCRTSdkLib(UniversalCRTSdkPath);
  153. sys::path::append(UCRTSdkLib, "Lib", UCRTVersion, "ucrt", "x64");
  154. ToolchainPath.UCRTSdkLib = UCRTSdkLib;
  155. return ToolchainPath;
  156. }