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