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