1 //===------- COFFVCRuntimeSupport.cpp - VC runtime support in ORC ---------===//
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
7 //===----------------------------------------------------------------------===//
9 #include "llvm/ExecutionEngine/Orc/COFFVCRuntimeSupport.h"
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"
16 #define DEBUG_TYPE "orc"
19 using namespace llvm::orc
;
20 using namespace llvm::orc::shared
;
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
));
30 COFFVCRuntimeBootstrapper::COFFVCRuntimeBootstrapper(
31 ExecutionSession
&ES
, ObjectLinkingLayer
&ObjLinkingLayer
,
32 const char *RuntimePath
)
33 : ES(ES
), ObjLinkingLayer(ObjLinkingLayer
) {
35 this->RuntimePath
= RuntimePath
;
38 Expected
<std::vector
<std::string
>>
39 COFFVCRuntimeBootstrapper::loadStaticVCRuntime(JITDylib
&JD
,
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
),
46 return std::move(Err
);
47 return ImportedLibraries
;
50 Expected
<std::vector
<std::string
>>
51 COFFVCRuntimeBootstrapper::loadDynamicVCRuntime(JITDylib
&JD
,
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
),
58 return std::move(Err
);
59 return ImportedLibraries
;
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
;
70 auto ToolchainPath
= getMSVCToolchainPath();
72 return ToolchainPath
.takeError();
73 Path
= *ToolchainPath
;
76 dbgs() << "Using VC toolchain pathes\n";
77 dbgs() << " VC toolchain path: " << Path
.VCToolchainLib
<< "\n";
78 dbgs() << " UCRT path: " << Path
.UCRTSdkLib
<< "\n";
81 auto LoadLibrary
= [&](SmallString
<256> LibPath
, StringRef LibName
) -> Error
{
82 sys::path::append(LibPath
, LibName
);
84 auto G
= StaticLibraryDefinitionGenerator::Load(ObjLinkingLayer
,
89 for (auto &Lib
: (*G
)->getImportedDynamicLibraries())
90 ImportedLibraries
.push_back(Lib
);
92 JD
.addGenerator(std::move(*G
));
94 return Error::success();
96 for (auto &Lib
: UCRTLibs
)
97 if (auto Err
= LoadLibrary(Path
.UCRTSdkLib
, Lib
))
100 for (auto &Lib
: VCLibs
)
101 if (auto Err
= LoadLibrary(Path
.VCToolchainLib
, Lib
))
103 ImportedLibraries
.push_back("ntdll.dll");
104 ImportedLibraries
.push_back("Kernel32.dll");
106 return Error::success();
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
}}))
124 auto RunVoidInitFunc
= [&](ExecutorAddr Addr
) -> Error
{
125 if (auto Res
= ES
.getExecutorProcessControl().runAsVoidFunction(Addr
))
126 return Error::success();
128 return Res
.takeError();
132 ES
.getExecutorProcessControl().runAsIntFunction(jit_scrt_initialize
, 0);
134 return R
.takeError();
136 if (auto Err
= RunVoidInitFunc(jit_scrt_dllmain_before_initialize_c
))
139 if (auto Err
= RunVoidInitFunc(jit_scrt_initialize_type_info
))
143 RunVoidInitFunc(jit_scrt_initialize_default_local_stdio_options
))
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
)))
152 return Error::success();
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());
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());
175 MSVCToolchainPath ToolchainPath
;
176 SmallString
<256> VCToolchainLib(VCToolChainPath
);
177 sys::path::append(VCToolchainLib
, "lib", "x64");
178 ToolchainPath
.VCToolchainLib
= VCToolchainLib
;
180 SmallString
<256> UCRTSdkLib(UniversalCRTSdkPath
);
181 sys::path::append(UCRTSdkLib
, "Lib", UCRTVersion
, "ucrt", "x64");
182 ToolchainPath
.UCRTSdkLib
= UCRTSdkLib
;
183 return ToolchainPath
;