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