1b749ef9eSLang Hames //===------ ELFNixPlatform.cpp - Utilities for executing MachO in Orc -----===//
2b749ef9eSLang Hames //
3b749ef9eSLang Hames // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4b749ef9eSLang Hames // See https://llvm.org/LICENSE.txt for license information.
5b749ef9eSLang Hames // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6b749ef9eSLang Hames //
7b749ef9eSLang Hames //===----------------------------------------------------------------------===//
8b749ef9eSLang Hames
9b749ef9eSLang Hames #include "llvm/ExecutionEngine/Orc/ELFNixPlatform.h"
10b749ef9eSLang Hames
11b749ef9eSLang Hames #include "llvm/BinaryFormat/ELF.h"
12b749ef9eSLang Hames #include "llvm/ExecutionEngine/JITLink/ELF_x86_64.h"
13e093e421SSunho Kim #include "llvm/ExecutionEngine/JITLink/aarch64.h"
14b749ef9eSLang Hames #include "llvm/ExecutionEngine/JITLink/x86_64.h"
15b749ef9eSLang Hames #include "llvm/ExecutionEngine/Orc/DebugUtils.h"
16b749ef9eSLang Hames #include "llvm/ExecutionEngine/Orc/ExecutionUtils.h"
17b749ef9eSLang Hames #include "llvm/Support/BinaryByteStream.h"
18b749ef9eSLang Hames #include "llvm/Support/Debug.h"
19b749ef9eSLang Hames
20b749ef9eSLang Hames #define DEBUG_TYPE "orc"
21b749ef9eSLang Hames
22b749ef9eSLang Hames using namespace llvm;
23b749ef9eSLang Hames using namespace llvm::orc;
24b749ef9eSLang Hames using namespace llvm::orc::shared;
25b749ef9eSLang Hames
26b749ef9eSLang Hames namespace {
27b749ef9eSLang Hames
28b749ef9eSLang Hames class DSOHandleMaterializationUnit : public MaterializationUnit {
29b749ef9eSLang Hames public:
DSOHandleMaterializationUnit(ELFNixPlatform & ENP,const SymbolStringPtr & DSOHandleSymbol)30b749ef9eSLang Hames DSOHandleMaterializationUnit(ELFNixPlatform &ENP,
31b749ef9eSLang Hames const SymbolStringPtr &DSOHandleSymbol)
32ae73f3fdSLang Hames : MaterializationUnit(
33ae73f3fdSLang Hames createDSOHandleSectionInterface(ENP, DSOHandleSymbol)),
34b749ef9eSLang Hames ENP(ENP) {}
35b749ef9eSLang Hames
getName() const36b749ef9eSLang Hames StringRef getName() const override { return "DSOHandleMU"; }
37b749ef9eSLang Hames
materialize(std::unique_ptr<MaterializationResponsibility> R)38b749ef9eSLang Hames void materialize(std::unique_ptr<MaterializationResponsibility> R) override {
39b749ef9eSLang Hames unsigned PointerSize;
40b749ef9eSLang Hames support::endianness Endianness;
41b749ef9eSLang Hames jitlink::Edge::Kind EdgeKind;
42b749ef9eSLang Hames const auto &TT =
43b749ef9eSLang Hames ENP.getExecutionSession().getExecutorProcessControl().getTargetTriple();
44b749ef9eSLang Hames
45b749ef9eSLang Hames switch (TT.getArch()) {
46b749ef9eSLang Hames case Triple::x86_64:
47b749ef9eSLang Hames PointerSize = 8;
48b749ef9eSLang Hames Endianness = support::endianness::little;
49b749ef9eSLang Hames EdgeKind = jitlink::x86_64::Pointer64;
50b749ef9eSLang Hames break;
51e093e421SSunho Kim case Triple::aarch64:
52e093e421SSunho Kim PointerSize = 8;
53e093e421SSunho Kim Endianness = support::endianness::little;
54e093e421SSunho Kim EdgeKind = jitlink::aarch64::Pointer64;
55e093e421SSunho Kim break;
56b749ef9eSLang Hames default:
57b749ef9eSLang Hames llvm_unreachable("Unrecognized architecture");
58b749ef9eSLang Hames }
59b749ef9eSLang Hames
60b749ef9eSLang Hames // void *__dso_handle = &__dso_handle;
61b749ef9eSLang Hames auto G = std::make_unique<jitlink::LinkGraph>(
62b749ef9eSLang Hames "<DSOHandleMU>", TT, PointerSize, Endianness,
63b749ef9eSLang Hames jitlink::getGenericEdgeKindName);
64b749ef9eSLang Hames auto &DSOHandleSection =
65962a2479SLang Hames G->createSection(".data.__dso_handle", jitlink::MemProt::Read);
66b749ef9eSLang Hames auto &DSOHandleBlock = G->createContentBlock(
67118e953bSLang Hames DSOHandleSection, getDSOHandleContent(PointerSize), orc::ExecutorAddr(),
68118e953bSLang Hames 8, 0);
69b749ef9eSLang Hames auto &DSOHandleSymbol = G->addDefinedSymbol(
70b749ef9eSLang Hames DSOHandleBlock, 0, *R->getInitializerSymbol(), DSOHandleBlock.getSize(),
71b749ef9eSLang Hames jitlink::Linkage::Strong, jitlink::Scope::Default, false, true);
72b749ef9eSLang Hames DSOHandleBlock.addEdge(EdgeKind, 0, DSOHandleSymbol, 0);
73b749ef9eSLang Hames
74b749ef9eSLang Hames ENP.getObjectLinkingLayer().emit(std::move(R), std::move(G));
75b749ef9eSLang Hames }
76b749ef9eSLang Hames
discard(const JITDylib & JD,const SymbolStringPtr & Sym)77b749ef9eSLang Hames void discard(const JITDylib &JD, const SymbolStringPtr &Sym) override {}
78b749ef9eSLang Hames
79b749ef9eSLang Hames private:
80ae73f3fdSLang Hames static MaterializationUnit::Interface
createDSOHandleSectionInterface(ELFNixPlatform & ENP,const SymbolStringPtr & DSOHandleSymbol)81ae73f3fdSLang Hames createDSOHandleSectionInterface(ELFNixPlatform &ENP,
82b749ef9eSLang Hames const SymbolStringPtr &DSOHandleSymbol) {
83b749ef9eSLang Hames SymbolFlagsMap SymbolFlags;
84b749ef9eSLang Hames SymbolFlags[DSOHandleSymbol] = JITSymbolFlags::Exported;
85ae73f3fdSLang Hames return MaterializationUnit::Interface(std::move(SymbolFlags),
86ae73f3fdSLang Hames DSOHandleSymbol);
87b749ef9eSLang Hames }
88b749ef9eSLang Hames
getDSOHandleContent(size_t PointerSize)89b749ef9eSLang Hames ArrayRef<char> getDSOHandleContent(size_t PointerSize) {
90b749ef9eSLang Hames static const char Content[8] = {0};
91b749ef9eSLang Hames assert(PointerSize <= sizeof Content);
92b749ef9eSLang Hames return {Content, PointerSize};
93b749ef9eSLang Hames }
94b749ef9eSLang Hames
95b749ef9eSLang Hames ELFNixPlatform &ENP;
96b749ef9eSLang Hames };
97b749ef9eSLang Hames
98b749ef9eSLang Hames StringRef EHFrameSectionName = ".eh_frame";
99b749ef9eSLang Hames StringRef InitArrayFuncSectionName = ".init_array";
100b749ef9eSLang Hames
101b749ef9eSLang Hames StringRef ThreadBSSSectionName = ".tbss";
102b749ef9eSLang Hames StringRef ThreadDataSectionName = ".tdata";
103b749ef9eSLang Hames
104b749ef9eSLang Hames } // end anonymous namespace
105b749ef9eSLang Hames
106b749ef9eSLang Hames namespace llvm {
107b749ef9eSLang Hames namespace orc {
108b749ef9eSLang Hames
109b749ef9eSLang Hames Expected<std::unique_ptr<ELFNixPlatform>>
Create(ExecutionSession & ES,ObjectLinkingLayer & ObjLinkingLayer,JITDylib & PlatformJD,const char * OrcRuntimePath,Optional<SymbolAliasMap> RuntimeAliases)110b749ef9eSLang Hames ELFNixPlatform::Create(ExecutionSession &ES,
111b749ef9eSLang Hames ObjectLinkingLayer &ObjLinkingLayer,
112b749ef9eSLang Hames JITDylib &PlatformJD, const char *OrcRuntimePath,
113b749ef9eSLang Hames Optional<SymbolAliasMap> RuntimeAliases) {
114b749ef9eSLang Hames
115b749ef9eSLang Hames auto &EPC = ES.getExecutorProcessControl();
116b749ef9eSLang Hames
117b749ef9eSLang Hames // If the target is not supported then bail out immediately.
118b749ef9eSLang Hames if (!supportedTarget(EPC.getTargetTriple()))
119b749ef9eSLang Hames return make_error<StringError>("Unsupported ELFNixPlatform triple: " +
120b749ef9eSLang Hames EPC.getTargetTriple().str(),
121b749ef9eSLang Hames inconvertibleErrorCode());
122b749ef9eSLang Hames
123b749ef9eSLang Hames // Create default aliases if the caller didn't supply any.
124981523b2SPeter S. Housel if (!RuntimeAliases) {
125981523b2SPeter S. Housel auto StandardRuntimeAliases = standardPlatformAliases(ES, PlatformJD);
126981523b2SPeter S. Housel if (!StandardRuntimeAliases)
127981523b2SPeter S. Housel return StandardRuntimeAliases.takeError();
128981523b2SPeter S. Housel RuntimeAliases = std::move(*StandardRuntimeAliases);
129981523b2SPeter S. Housel }
130b749ef9eSLang Hames
131b749ef9eSLang Hames // Define the aliases.
132b749ef9eSLang Hames if (auto Err = PlatformJD.define(symbolAliases(std::move(*RuntimeAliases))))
133b749ef9eSLang Hames return std::move(Err);
134b749ef9eSLang Hames
135b749ef9eSLang Hames // Add JIT-dispatch function support symbols.
136b749ef9eSLang Hames if (auto Err = PlatformJD.define(absoluteSymbols(
137b749ef9eSLang Hames {{ES.intern("__orc_rt_jit_dispatch"),
138ef391df2SLang Hames {EPC.getJITDispatchInfo().JITDispatchFunction.getValue(),
139b749ef9eSLang Hames JITSymbolFlags::Exported}},
140b749ef9eSLang Hames {ES.intern("__orc_rt_jit_dispatch_ctx"),
141ef391df2SLang Hames {EPC.getJITDispatchInfo().JITDispatchContext.getValue(),
142b749ef9eSLang Hames JITSymbolFlags::Exported}}})))
143b749ef9eSLang Hames return std::move(Err);
144b749ef9eSLang Hames
145b749ef9eSLang Hames // Create a generator for the ORC runtime archive.
146b749ef9eSLang Hames auto OrcRuntimeArchiveGenerator = StaticLibraryDefinitionGenerator::Load(
147b749ef9eSLang Hames ObjLinkingLayer, OrcRuntimePath, EPC.getTargetTriple());
148b749ef9eSLang Hames if (!OrcRuntimeArchiveGenerator)
149b749ef9eSLang Hames return OrcRuntimeArchiveGenerator.takeError();
150b749ef9eSLang Hames
151b749ef9eSLang Hames // Create the instance.
152b749ef9eSLang Hames Error Err = Error::success();
153b749ef9eSLang Hames auto P = std::unique_ptr<ELFNixPlatform>(
154b749ef9eSLang Hames new ELFNixPlatform(ES, ObjLinkingLayer, PlatformJD,
155b749ef9eSLang Hames std::move(*OrcRuntimeArchiveGenerator), Err));
156b749ef9eSLang Hames if (Err)
157b749ef9eSLang Hames return std::move(Err);
158b749ef9eSLang Hames return std::move(P);
159b749ef9eSLang Hames }
160b749ef9eSLang Hames
setupJITDylib(JITDylib & JD)161b749ef9eSLang Hames Error ELFNixPlatform::setupJITDylib(JITDylib &JD) {
162b749ef9eSLang Hames return JD.define(
163b749ef9eSLang Hames std::make_unique<DSOHandleMaterializationUnit>(*this, DSOHandleSymbol));
164b749ef9eSLang Hames }
165b749ef9eSLang Hames
teardownJITDylib(JITDylib & JD)166ade71641SLang Hames Error ELFNixPlatform::teardownJITDylib(JITDylib &JD) {
167ade71641SLang Hames return Error::success();
168ade71641SLang Hames }
169ade71641SLang Hames
notifyAdding(ResourceTracker & RT,const MaterializationUnit & MU)170b749ef9eSLang Hames Error ELFNixPlatform::notifyAdding(ResourceTracker &RT,
171b749ef9eSLang Hames const MaterializationUnit &MU) {
172b749ef9eSLang Hames auto &JD = RT.getJITDylib();
173b749ef9eSLang Hames const auto &InitSym = MU.getInitializerSymbol();
174b749ef9eSLang Hames if (!InitSym)
175b749ef9eSLang Hames return Error::success();
176b749ef9eSLang Hames
177b749ef9eSLang Hames RegisteredInitSymbols[&JD].add(InitSym,
178b749ef9eSLang Hames SymbolLookupFlags::WeaklyReferencedSymbol);
179b749ef9eSLang Hames LLVM_DEBUG({
180b749ef9eSLang Hames dbgs() << "ELFNixPlatform: Registered init symbol " << *InitSym
181b749ef9eSLang Hames << " for MU " << MU.getName() << "\n";
182b749ef9eSLang Hames });
183b749ef9eSLang Hames return Error::success();
184b749ef9eSLang Hames }
185b749ef9eSLang Hames
notifyRemoving(ResourceTracker & RT)186b749ef9eSLang Hames Error ELFNixPlatform::notifyRemoving(ResourceTracker &RT) {
187b749ef9eSLang Hames llvm_unreachable("Not supported yet");
188b749ef9eSLang Hames }
189b749ef9eSLang Hames
addAliases(ExecutionSession & ES,SymbolAliasMap & Aliases,ArrayRef<std::pair<const char *,const char * >> AL)190b749ef9eSLang Hames static void addAliases(ExecutionSession &ES, SymbolAliasMap &Aliases,
191b749ef9eSLang Hames ArrayRef<std::pair<const char *, const char *>> AL) {
192b749ef9eSLang Hames for (auto &KV : AL) {
193b749ef9eSLang Hames auto AliasName = ES.intern(KV.first);
194b749ef9eSLang Hames assert(!Aliases.count(AliasName) && "Duplicate symbol name in alias map");
195b749ef9eSLang Hames Aliases[std::move(AliasName)] = {ES.intern(KV.second),
196b749ef9eSLang Hames JITSymbolFlags::Exported};
197b749ef9eSLang Hames }
198b749ef9eSLang Hames }
199b749ef9eSLang Hames
200981523b2SPeter S. Housel Expected<SymbolAliasMap>
standardPlatformAliases(ExecutionSession & ES,JITDylib & PlatformJD)201981523b2SPeter S. Housel ELFNixPlatform::standardPlatformAliases(ExecutionSession &ES,
202981523b2SPeter S. Housel JITDylib &PlatformJD) {
203b749ef9eSLang Hames SymbolAliasMap Aliases;
204b749ef9eSLang Hames addAliases(ES, Aliases, requiredCXXAliases());
205b749ef9eSLang Hames addAliases(ES, Aliases, standardRuntimeUtilityAliases());
206981523b2SPeter S. Housel
207981523b2SPeter S. Housel // Determine whether or not the libunwind extended-API function for
208981523b2SPeter S. Housel // dynamically registering an entire .eh_frame section is available.
209981523b2SPeter S. Housel // If it is not, we assume that libgcc_s is being used, and alias to
210981523b2SPeter S. Housel // its __register_frame with the same functionality.
211981523b2SPeter S. Housel auto RTRegisterFrame = ES.intern("__orc_rt_register_eh_frame_section");
212981523b2SPeter S. Housel auto LibUnwindRegisterFrame = ES.intern("__unw_add_dynamic_eh_frame_section");
213981523b2SPeter S. Housel auto RTDeregisterFrame = ES.intern("__orc_rt_deregister_eh_frame_section");
214981523b2SPeter S. Housel auto LibUnwindDeregisterFrame =
215981523b2SPeter S. Housel ES.intern("__unw_remove_dynamic_eh_frame_section");
216981523b2SPeter S. Housel auto SM = ES.lookup(makeJITDylibSearchOrder(&PlatformJD),
217981523b2SPeter S. Housel SymbolLookupSet()
218981523b2SPeter S. Housel .add(LibUnwindRegisterFrame,
219981523b2SPeter S. Housel SymbolLookupFlags::WeaklyReferencedSymbol)
220981523b2SPeter S. Housel .add(LibUnwindDeregisterFrame,
221981523b2SPeter S. Housel SymbolLookupFlags::WeaklyReferencedSymbol));
222981523b2SPeter S. Housel if (!SM) { // Weak-ref means no "missing symbol" errors, so this must be
223981523b2SPeter S. Housel // something more serious that we should report.
224981523b2SPeter S. Housel return SM.takeError();
225981523b2SPeter S. Housel } else if (SM->size() == 2) {
226981523b2SPeter S. Housel LLVM_DEBUG({
227981523b2SPeter S. Housel dbgs() << "Using libunwind " << LibUnwindRegisterFrame
228981523b2SPeter S. Housel << " for unwind info registration\n";
229981523b2SPeter S. Housel });
230981523b2SPeter S. Housel Aliases[std::move(RTRegisterFrame)] = {LibUnwindRegisterFrame,
231981523b2SPeter S. Housel JITSymbolFlags::Exported};
232981523b2SPeter S. Housel Aliases[std::move(RTDeregisterFrame)] = {LibUnwindDeregisterFrame,
233981523b2SPeter S. Housel JITSymbolFlags::Exported};
234981523b2SPeter S. Housel } else {
235981523b2SPeter S. Housel // Since LLVM libunwind is not present, we assume that unwinding
236981523b2SPeter S. Housel // is provided by libgcc
237981523b2SPeter S. Housel LLVM_DEBUG({
238981523b2SPeter S. Housel dbgs() << "Using libgcc __register_frame"
239981523b2SPeter S. Housel << " for unwind info registration\n";
240981523b2SPeter S. Housel });
241981523b2SPeter S. Housel Aliases[std::move(RTRegisterFrame)] = {ES.intern("__register_frame"),
242981523b2SPeter S. Housel JITSymbolFlags::Exported};
243981523b2SPeter S. Housel Aliases[std::move(RTDeregisterFrame)] = {ES.intern("__deregister_frame"),
244981523b2SPeter S. Housel JITSymbolFlags::Exported};
245981523b2SPeter S. Housel }
246981523b2SPeter S. Housel
247b749ef9eSLang Hames return Aliases;
248b749ef9eSLang Hames }
249b749ef9eSLang Hames
250b749ef9eSLang Hames ArrayRef<std::pair<const char *, const char *>>
requiredCXXAliases()251b749ef9eSLang Hames ELFNixPlatform::requiredCXXAliases() {
252b749ef9eSLang Hames static const std::pair<const char *, const char *> RequiredCXXAliases[] = {
25359032638Sluxufan {"__cxa_atexit", "__orc_rt_elfnix_cxa_atexit"},
25459032638Sluxufan {"atexit", "__orc_rt_elfnix_atexit"}};
255b749ef9eSLang Hames
256b749ef9eSLang Hames return ArrayRef<std::pair<const char *, const char *>>(RequiredCXXAliases);
257b749ef9eSLang Hames }
258b749ef9eSLang Hames
259b749ef9eSLang Hames ArrayRef<std::pair<const char *, const char *>>
standardRuntimeUtilityAliases()260b749ef9eSLang Hames ELFNixPlatform::standardRuntimeUtilityAliases() {
261b749ef9eSLang Hames static const std::pair<const char *, const char *>
262b749ef9eSLang Hames StandardRuntimeUtilityAliases[] = {
263b749ef9eSLang Hames {"__orc_rt_run_program", "__orc_rt_elfnix_run_program"},
2641aa71f86SPeter S. Housel {"__orc_rt_jit_dlerror", "__orc_rt_elfnix_jit_dlerror"},
2651aa71f86SPeter S. Housel {"__orc_rt_jit_dlopen", "__orc_rt_elfnix_jit_dlopen"},
2661aa71f86SPeter S. Housel {"__orc_rt_jit_dlclose", "__orc_rt_elfnix_jit_dlclose"},
2671aa71f86SPeter S. Housel {"__orc_rt_jit_dlsym", "__orc_rt_elfnix_jit_dlsym"},
268b749ef9eSLang Hames {"__orc_rt_log_error", "__orc_rt_log_error_to_stderr"}};
269b749ef9eSLang Hames
270b749ef9eSLang Hames return ArrayRef<std::pair<const char *, const char *>>(
271b749ef9eSLang Hames StandardRuntimeUtilityAliases);
272b749ef9eSLang Hames }
273b749ef9eSLang Hames
isInitializerSection(StringRef SecName)274b749ef9eSLang Hames bool ELFNixPlatform::isInitializerSection(StringRef SecName) {
2752be5abb7SPeter S. Housel if (SecName.consume_front(InitArrayFuncSectionName) &&
2762be5abb7SPeter S. Housel (SecName.empty() || SecName[0] == '.'))
277b749ef9eSLang Hames return true;
278b749ef9eSLang Hames return false;
279b749ef9eSLang Hames }
280b749ef9eSLang Hames
supportedTarget(const Triple & TT)281b749ef9eSLang Hames bool ELFNixPlatform::supportedTarget(const Triple &TT) {
282b749ef9eSLang Hames switch (TT.getArch()) {
283b749ef9eSLang Hames case Triple::x86_64:
284e093e421SSunho Kim case Triple::aarch64:
285b749ef9eSLang Hames return true;
286b749ef9eSLang Hames default:
287b749ef9eSLang Hames return false;
288b749ef9eSLang Hames }
289b749ef9eSLang Hames }
290b749ef9eSLang Hames
ELFNixPlatform(ExecutionSession & ES,ObjectLinkingLayer & ObjLinkingLayer,JITDylib & PlatformJD,std::unique_ptr<DefinitionGenerator> OrcRuntimeGenerator,Error & Err)291b749ef9eSLang Hames ELFNixPlatform::ELFNixPlatform(
292b749ef9eSLang Hames ExecutionSession &ES, ObjectLinkingLayer &ObjLinkingLayer,
293b749ef9eSLang Hames JITDylib &PlatformJD,
294b749ef9eSLang Hames std::unique_ptr<DefinitionGenerator> OrcRuntimeGenerator, Error &Err)
295b749ef9eSLang Hames : ES(ES), ObjLinkingLayer(ObjLinkingLayer),
296b749ef9eSLang Hames DSOHandleSymbol(ES.intern("__dso_handle")) {
297b749ef9eSLang Hames ErrorAsOutParameter _(&Err);
298b749ef9eSLang Hames
299b749ef9eSLang Hames ObjLinkingLayer.addPlugin(std::make_unique<ELFNixPlatformPlugin>(*this));
300b749ef9eSLang Hames
301b749ef9eSLang Hames PlatformJD.addGenerator(std::move(OrcRuntimeGenerator));
302b749ef9eSLang Hames
303b749ef9eSLang Hames // PlatformJD hasn't been 'set-up' by the platform yet (since we're creating
304b749ef9eSLang Hames // the platform now), so set it up.
305b749ef9eSLang Hames if (auto E2 = setupJITDylib(PlatformJD)) {
306b749ef9eSLang Hames Err = std::move(E2);
307b749ef9eSLang Hames return;
308b749ef9eSLang Hames }
309b749ef9eSLang Hames
310b749ef9eSLang Hames RegisteredInitSymbols[&PlatformJD].add(
311b749ef9eSLang Hames DSOHandleSymbol, SymbolLookupFlags::WeaklyReferencedSymbol);
312b749ef9eSLang Hames
313b749ef9eSLang Hames // Associate wrapper function tags with JIT-side function implementations.
314b749ef9eSLang Hames if (auto E2 = associateRuntimeSupportFunctions(PlatformJD)) {
315b749ef9eSLang Hames Err = std::move(E2);
316b749ef9eSLang Hames return;
317b749ef9eSLang Hames }
318b749ef9eSLang Hames
319b749ef9eSLang Hames // Lookup addresses of runtime functions callable by the platform,
320b749ef9eSLang Hames // call the platform bootstrap function to initialize the platform-state
321b749ef9eSLang Hames // object in the executor.
322b749ef9eSLang Hames if (auto E2 = bootstrapELFNixRuntime(PlatformJD)) {
323b749ef9eSLang Hames Err = std::move(E2);
324b749ef9eSLang Hames return;
325b749ef9eSLang Hames }
326b749ef9eSLang Hames }
327b749ef9eSLang Hames
associateRuntimeSupportFunctions(JITDylib & PlatformJD)328b749ef9eSLang Hames Error ELFNixPlatform::associateRuntimeSupportFunctions(JITDylib &PlatformJD) {
329b749ef9eSLang Hames ExecutionSession::JITDispatchHandlerAssociationMap WFs;
330b749ef9eSLang Hames
331b749ef9eSLang Hames using GetInitializersSPSSig =
332b749ef9eSLang Hames SPSExpected<SPSELFNixJITDylibInitializerSequence>(SPSString);
333b749ef9eSLang Hames WFs[ES.intern("__orc_rt_elfnix_get_initializers_tag")] =
334b749ef9eSLang Hames ES.wrapAsyncWithSPS<GetInitializersSPSSig>(
335b749ef9eSLang Hames this, &ELFNixPlatform::rt_getInitializers);
336b749ef9eSLang Hames
337b749ef9eSLang Hames using GetDeinitializersSPSSig =
338ef391df2SLang Hames SPSExpected<SPSELFJITDylibDeinitializerSequence>(SPSExecutorAddr);
339b749ef9eSLang Hames WFs[ES.intern("__orc_rt_elfnix_get_deinitializers_tag")] =
340b749ef9eSLang Hames ES.wrapAsyncWithSPS<GetDeinitializersSPSSig>(
341b749ef9eSLang Hames this, &ELFNixPlatform::rt_getDeinitializers);
342b749ef9eSLang Hames
343b749ef9eSLang Hames using LookupSymbolSPSSig =
344ef391df2SLang Hames SPSExpected<SPSExecutorAddr>(SPSExecutorAddr, SPSString);
345b749ef9eSLang Hames WFs[ES.intern("__orc_rt_elfnix_symbol_lookup_tag")] =
346b749ef9eSLang Hames ES.wrapAsyncWithSPS<LookupSymbolSPSSig>(this,
347b749ef9eSLang Hames &ELFNixPlatform::rt_lookupSymbol);
348b749ef9eSLang Hames
349b749ef9eSLang Hames return ES.registerJITDispatchHandlers(PlatformJD, std::move(WFs));
350b749ef9eSLang Hames }
351b749ef9eSLang Hames
getInitializersBuildSequencePhase(SendInitializerSequenceFn SendResult,JITDylib & JD,std::vector<JITDylibSP> DFSLinkOrder)352b749ef9eSLang Hames void ELFNixPlatform::getInitializersBuildSequencePhase(
353b749ef9eSLang Hames SendInitializerSequenceFn SendResult, JITDylib &JD,
354b749ef9eSLang Hames std::vector<JITDylibSP> DFSLinkOrder) {
355b749ef9eSLang Hames ELFNixJITDylibInitializerSequence FullInitSeq;
356b749ef9eSLang Hames {
357b749ef9eSLang Hames std::lock_guard<std::mutex> Lock(PlatformMutex);
358b749ef9eSLang Hames for (auto &InitJD : reverse(DFSLinkOrder)) {
359b749ef9eSLang Hames LLVM_DEBUG({
360b749ef9eSLang Hames dbgs() << "ELFNixPlatform: Appending inits for \"" << InitJD->getName()
361b749ef9eSLang Hames << "\" to sequence\n";
362b749ef9eSLang Hames });
363b749ef9eSLang Hames auto ISItr = InitSeqs.find(InitJD.get());
364b749ef9eSLang Hames if (ISItr != InitSeqs.end()) {
365b749ef9eSLang Hames FullInitSeq.emplace_back(std::move(ISItr->second));
366b749ef9eSLang Hames InitSeqs.erase(ISItr);
367b749ef9eSLang Hames }
368b749ef9eSLang Hames }
369b749ef9eSLang Hames }
370b749ef9eSLang Hames
371b749ef9eSLang Hames SendResult(std::move(FullInitSeq));
372b749ef9eSLang Hames }
373b749ef9eSLang Hames
getInitializersLookupPhase(SendInitializerSequenceFn SendResult,JITDylib & JD)374b749ef9eSLang Hames void ELFNixPlatform::getInitializersLookupPhase(
375b749ef9eSLang Hames SendInitializerSequenceFn SendResult, JITDylib &JD) {
376b749ef9eSLang Hames
377b749ef9eSLang Hames auto DFSLinkOrder = JD.getDFSLinkOrder();
3789eb4939bSLang Hames if (!DFSLinkOrder) {
3799eb4939bSLang Hames SendResult(DFSLinkOrder.takeError());
3809eb4939bSLang Hames return;
3819eb4939bSLang Hames }
3829eb4939bSLang Hames
383b749ef9eSLang Hames DenseMap<JITDylib *, SymbolLookupSet> NewInitSymbols;
384b749ef9eSLang Hames ES.runSessionLocked([&]() {
3859eb4939bSLang Hames for (auto &InitJD : *DFSLinkOrder) {
386b749ef9eSLang Hames auto RISItr = RegisteredInitSymbols.find(InitJD.get());
387b749ef9eSLang Hames if (RISItr != RegisteredInitSymbols.end()) {
388b749ef9eSLang Hames NewInitSymbols[InitJD.get()] = std::move(RISItr->second);
389b749ef9eSLang Hames RegisteredInitSymbols.erase(RISItr);
390b749ef9eSLang Hames }
391b749ef9eSLang Hames }
392b749ef9eSLang Hames });
393b749ef9eSLang Hames
394b749ef9eSLang Hames // If there are no further init symbols to look up then move on to the next
395b749ef9eSLang Hames // phase.
396b749ef9eSLang Hames if (NewInitSymbols.empty()) {
397b749ef9eSLang Hames getInitializersBuildSequencePhase(std::move(SendResult), JD,
3989eb4939bSLang Hames std::move(*DFSLinkOrder));
399b749ef9eSLang Hames return;
400b749ef9eSLang Hames }
401b749ef9eSLang Hames
402b749ef9eSLang Hames // Otherwise issue a lookup and re-run this phase when it completes.
403b749ef9eSLang Hames lookupInitSymbolsAsync(
404b749ef9eSLang Hames [this, SendResult = std::move(SendResult), &JD](Error Err) mutable {
405b749ef9eSLang Hames if (Err)
406b749ef9eSLang Hames SendResult(std::move(Err));
407b749ef9eSLang Hames else
408b749ef9eSLang Hames getInitializersLookupPhase(std::move(SendResult), JD);
409b749ef9eSLang Hames },
410b749ef9eSLang Hames ES, std::move(NewInitSymbols));
411b749ef9eSLang Hames }
412b749ef9eSLang Hames
rt_getInitializers(SendInitializerSequenceFn SendResult,StringRef JDName)413b749ef9eSLang Hames void ELFNixPlatform::rt_getInitializers(SendInitializerSequenceFn SendResult,
414b749ef9eSLang Hames StringRef JDName) {
415b749ef9eSLang Hames LLVM_DEBUG({
416b749ef9eSLang Hames dbgs() << "ELFNixPlatform::rt_getInitializers(\"" << JDName << "\")\n";
417b749ef9eSLang Hames });
418b749ef9eSLang Hames
419b749ef9eSLang Hames JITDylib *JD = ES.getJITDylibByName(JDName);
420b749ef9eSLang Hames if (!JD) {
421b749ef9eSLang Hames LLVM_DEBUG({
422b749ef9eSLang Hames dbgs() << " No such JITDylib \"" << JDName << "\". Sending error.\n";
423b749ef9eSLang Hames });
424b749ef9eSLang Hames SendResult(make_error<StringError>("No JITDylib named " + JDName,
425b749ef9eSLang Hames inconvertibleErrorCode()));
426b749ef9eSLang Hames return;
427b749ef9eSLang Hames }
428b749ef9eSLang Hames
429b749ef9eSLang Hames getInitializersLookupPhase(std::move(SendResult), *JD);
430b749ef9eSLang Hames }
431b749ef9eSLang Hames
rt_getDeinitializers(SendDeinitializerSequenceFn SendResult,ExecutorAddr Handle)432b749ef9eSLang Hames void ELFNixPlatform::rt_getDeinitializers(
433ef391df2SLang Hames SendDeinitializerSequenceFn SendResult, ExecutorAddr Handle) {
434b749ef9eSLang Hames LLVM_DEBUG({
435b749ef9eSLang Hames dbgs() << "ELFNixPlatform::rt_getDeinitializers(\""
436b749ef9eSLang Hames << formatv("{0:x}", Handle.getValue()) << "\")\n";
437b749ef9eSLang Hames });
438b749ef9eSLang Hames
439b749ef9eSLang Hames JITDylib *JD = nullptr;
440b749ef9eSLang Hames
441b749ef9eSLang Hames {
442b749ef9eSLang Hames std::lock_guard<std::mutex> Lock(PlatformMutex);
443118e953bSLang Hames auto I = HandleAddrToJITDylib.find(Handle);
444b749ef9eSLang Hames if (I != HandleAddrToJITDylib.end())
445b749ef9eSLang Hames JD = I->second;
446b749ef9eSLang Hames }
447b749ef9eSLang Hames
448b749ef9eSLang Hames if (!JD) {
449b749ef9eSLang Hames LLVM_DEBUG({
450b749ef9eSLang Hames dbgs() << " No JITDylib for handle "
451b749ef9eSLang Hames << formatv("{0:x}", Handle.getValue()) << "\n";
452b749ef9eSLang Hames });
453b749ef9eSLang Hames SendResult(make_error<StringError>("No JITDylib associated with handle " +
454b749ef9eSLang Hames formatv("{0:x}", Handle.getValue()),
455b749ef9eSLang Hames inconvertibleErrorCode()));
456b749ef9eSLang Hames return;
457b749ef9eSLang Hames }
458b749ef9eSLang Hames
459b749ef9eSLang Hames SendResult(ELFNixJITDylibDeinitializerSequence());
460b749ef9eSLang Hames }
461b749ef9eSLang Hames
rt_lookupSymbol(SendSymbolAddressFn SendResult,ExecutorAddr Handle,StringRef SymbolName)462b749ef9eSLang Hames void ELFNixPlatform::rt_lookupSymbol(SendSymbolAddressFn SendResult,
463ef391df2SLang Hames ExecutorAddr Handle,
464b749ef9eSLang Hames StringRef SymbolName) {
465b749ef9eSLang Hames LLVM_DEBUG({
466b749ef9eSLang Hames dbgs() << "ELFNixPlatform::rt_lookupSymbol(\""
467b749ef9eSLang Hames << formatv("{0:x}", Handle.getValue()) << "\")\n";
468b749ef9eSLang Hames });
469b749ef9eSLang Hames
470b749ef9eSLang Hames JITDylib *JD = nullptr;
471b749ef9eSLang Hames
472b749ef9eSLang Hames {
473b749ef9eSLang Hames std::lock_guard<std::mutex> Lock(PlatformMutex);
474118e953bSLang Hames auto I = HandleAddrToJITDylib.find(Handle);
475b749ef9eSLang Hames if (I != HandleAddrToJITDylib.end())
476b749ef9eSLang Hames JD = I->second;
477b749ef9eSLang Hames }
478b749ef9eSLang Hames
479b749ef9eSLang Hames if (!JD) {
480b749ef9eSLang Hames LLVM_DEBUG({
481b749ef9eSLang Hames dbgs() << " No JITDylib for handle "
482b749ef9eSLang Hames << formatv("{0:x}", Handle.getValue()) << "\n";
483b749ef9eSLang Hames });
484b749ef9eSLang Hames SendResult(make_error<StringError>("No JITDylib associated with handle " +
485b749ef9eSLang Hames formatv("{0:x}", Handle.getValue()),
486b749ef9eSLang Hames inconvertibleErrorCode()));
487b749ef9eSLang Hames return;
488b749ef9eSLang Hames }
489b749ef9eSLang Hames
490b749ef9eSLang Hames // Use functor class to work around XL build compiler issue on AIX.
491b749ef9eSLang Hames class RtLookupNotifyComplete {
492b749ef9eSLang Hames public:
493b749ef9eSLang Hames RtLookupNotifyComplete(SendSymbolAddressFn &&SendResult)
494b749ef9eSLang Hames : SendResult(std::move(SendResult)) {}
495b749ef9eSLang Hames void operator()(Expected<SymbolMap> Result) {
496b749ef9eSLang Hames if (Result) {
497b749ef9eSLang Hames assert(Result->size() == 1 && "Unexpected result map count");
498ef391df2SLang Hames SendResult(ExecutorAddr(Result->begin()->second.getAddress()));
499b749ef9eSLang Hames } else {
500b749ef9eSLang Hames SendResult(Result.takeError());
501b749ef9eSLang Hames }
502b749ef9eSLang Hames }
503b749ef9eSLang Hames
504b749ef9eSLang Hames private:
505b749ef9eSLang Hames SendSymbolAddressFn SendResult;
506b749ef9eSLang Hames };
507b749ef9eSLang Hames
508b749ef9eSLang Hames ES.lookup(
509b749ef9eSLang Hames LookupKind::DLSym, {{JD, JITDylibLookupFlags::MatchExportedSymbolsOnly}},
510b749ef9eSLang Hames SymbolLookupSet(ES.intern(SymbolName)), SymbolState::Ready,
511b749ef9eSLang Hames RtLookupNotifyComplete(std::move(SendResult)), NoDependenciesToRegister);
512b749ef9eSLang Hames }
513b749ef9eSLang Hames
bootstrapELFNixRuntime(JITDylib & PlatformJD)514b749ef9eSLang Hames Error ELFNixPlatform::bootstrapELFNixRuntime(JITDylib &PlatformJD) {
515b749ef9eSLang Hames
516ef391df2SLang Hames std::pair<const char *, ExecutorAddr *> Symbols[] = {
517b749ef9eSLang Hames {"__orc_rt_elfnix_platform_bootstrap", &orc_rt_elfnix_platform_bootstrap},
518b749ef9eSLang Hames {"__orc_rt_elfnix_platform_shutdown", &orc_rt_elfnix_platform_shutdown},
519b749ef9eSLang Hames {"__orc_rt_elfnix_register_object_sections",
520ff6069b8Sluxufan &orc_rt_elfnix_register_object_sections},
521ff6069b8Sluxufan {"__orc_rt_elfnix_create_pthread_key",
522ff6069b8Sluxufan &orc_rt_elfnix_create_pthread_key}};
523b749ef9eSLang Hames
524b749ef9eSLang Hames SymbolLookupSet RuntimeSymbols;
525ef391df2SLang Hames std::vector<std::pair<SymbolStringPtr, ExecutorAddr *>> AddrsToRecord;
526b749ef9eSLang Hames for (const auto &KV : Symbols) {
527b749ef9eSLang Hames auto Name = ES.intern(KV.first);
528b749ef9eSLang Hames RuntimeSymbols.add(Name);
529b749ef9eSLang Hames AddrsToRecord.push_back({std::move(Name), KV.second});
530b749ef9eSLang Hames }
531b749ef9eSLang Hames
532b749ef9eSLang Hames auto RuntimeSymbolAddrs = ES.lookup(
533b749ef9eSLang Hames {{&PlatformJD, JITDylibLookupFlags::MatchAllSymbols}}, RuntimeSymbols);
534b749ef9eSLang Hames if (!RuntimeSymbolAddrs)
535b749ef9eSLang Hames return RuntimeSymbolAddrs.takeError();
536b749ef9eSLang Hames
537b749ef9eSLang Hames for (const auto &KV : AddrsToRecord) {
538b749ef9eSLang Hames auto &Name = KV.first;
539b749ef9eSLang Hames assert(RuntimeSymbolAddrs->count(Name) && "Missing runtime symbol?");
540b749ef9eSLang Hames KV.second->setValue((*RuntimeSymbolAddrs)[Name].getAddress());
541b749ef9eSLang Hames }
542b749ef9eSLang Hames
54359032638Sluxufan auto PJDDSOHandle = ES.lookup(
54459032638Sluxufan {{&PlatformJD, JITDylibLookupFlags::MatchAllSymbols}}, DSOHandleSymbol);
54559032638Sluxufan if (!PJDDSOHandle)
54659032638Sluxufan return PJDDSOHandle.takeError();
54759032638Sluxufan
54859032638Sluxufan if (auto Err = ES.callSPSWrapper<void(uint64_t)>(
54959032638Sluxufan orc_rt_elfnix_platform_bootstrap, PJDDSOHandle->getAddress()))
550b749ef9eSLang Hames return Err;
551b749ef9eSLang Hames
552b749ef9eSLang Hames // FIXME: Ordering is fuzzy here. We're probably best off saying
553b749ef9eSLang Hames // "behavior is undefined if code that uses the runtime is added before
554b749ef9eSLang Hames // the platform constructor returns", then move all this to the constructor.
555b749ef9eSLang Hames RuntimeBootstrapped = true;
556b749ef9eSLang Hames std::vector<ELFPerObjectSectionsToRegister> DeferredPOSRs;
557b749ef9eSLang Hames {
558b749ef9eSLang Hames std::lock_guard<std::mutex> Lock(PlatformMutex);
559b749ef9eSLang Hames DeferredPOSRs = std::move(BootstrapPOSRs);
560b749ef9eSLang Hames }
561b749ef9eSLang Hames
562b749ef9eSLang Hames for (auto &D : DeferredPOSRs)
563b749ef9eSLang Hames if (auto Err = registerPerObjectSections(D))
564b749ef9eSLang Hames return Err;
565b749ef9eSLang Hames
566b749ef9eSLang Hames return Error::success();
567b749ef9eSLang Hames }
568b749ef9eSLang Hames
registerInitInfo(JITDylib & JD,ArrayRef<jitlink::Section * > InitSections)569b749ef9eSLang Hames Error ELFNixPlatform::registerInitInfo(
570b749ef9eSLang Hames JITDylib &JD, ArrayRef<jitlink::Section *> InitSections) {
571b749ef9eSLang Hames
572b749ef9eSLang Hames std::unique_lock<std::mutex> Lock(PlatformMutex);
573b749ef9eSLang Hames
574b749ef9eSLang Hames ELFNixJITDylibInitializers *InitSeq = nullptr;
575b749ef9eSLang Hames {
576b749ef9eSLang Hames auto I = InitSeqs.find(&JD);
577b749ef9eSLang Hames if (I == InitSeqs.end()) {
578b749ef9eSLang Hames // If there's no init sequence entry yet then we need to look up the
579b749ef9eSLang Hames // header symbol to force creation of one.
580b749ef9eSLang Hames Lock.unlock();
581b749ef9eSLang Hames
582b749ef9eSLang Hames auto SearchOrder =
583b749ef9eSLang Hames JD.withLinkOrderDo([](const JITDylibSearchOrder &SO) { return SO; });
584b749ef9eSLang Hames if (auto Err = ES.lookup(SearchOrder, DSOHandleSymbol).takeError())
585b749ef9eSLang Hames return Err;
586b749ef9eSLang Hames
587b749ef9eSLang Hames Lock.lock();
588b749ef9eSLang Hames I = InitSeqs.find(&JD);
589b749ef9eSLang Hames assert(I != InitSeqs.end() &&
590b749ef9eSLang Hames "Entry missing after header symbol lookup?");
591b749ef9eSLang Hames }
592b749ef9eSLang Hames InitSeq = &I->second;
593b749ef9eSLang Hames }
594b749ef9eSLang Hames
595b749ef9eSLang Hames for (auto *Sec : InitSections) {
596b749ef9eSLang Hames // FIXME: Avoid copy here.
597b749ef9eSLang Hames jitlink::SectionRange R(*Sec);
598b749ef9eSLang Hames InitSeq->InitSections[Sec->getName()].push_back(
599ef391df2SLang Hames {ExecutorAddr(R.getStart()), ExecutorAddr(R.getEnd())});
600b749ef9eSLang Hames }
601b749ef9eSLang Hames
602b749ef9eSLang Hames return Error::success();
603b749ef9eSLang Hames }
604b749ef9eSLang Hames
registerPerObjectSections(const ELFPerObjectSectionsToRegister & POSR)605b749ef9eSLang Hames Error ELFNixPlatform::registerPerObjectSections(
606b749ef9eSLang Hames const ELFPerObjectSectionsToRegister &POSR) {
607b749ef9eSLang Hames
608b749ef9eSLang Hames if (!orc_rt_elfnix_register_object_sections)
609b749ef9eSLang Hames return make_error<StringError>("Attempting to register per-object "
610b749ef9eSLang Hames "sections, but runtime support has not "
611b749ef9eSLang Hames "been loaded yet",
612b749ef9eSLang Hames inconvertibleErrorCode());
613b749ef9eSLang Hames
614b749ef9eSLang Hames Error ErrResult = Error::success();
615b749ef9eSLang Hames if (auto Err = ES.callSPSWrapper<shared::SPSError(
616b749ef9eSLang Hames SPSELFPerObjectSectionsToRegister)>(
61721a06254SLang Hames orc_rt_elfnix_register_object_sections, ErrResult, POSR))
618b749ef9eSLang Hames return Err;
619b749ef9eSLang Hames return ErrResult;
620b749ef9eSLang Hames }
621b749ef9eSLang Hames
createPThreadKey()622ff6069b8Sluxufan Expected<uint64_t> ELFNixPlatform::createPThreadKey() {
623ff6069b8Sluxufan if (!orc_rt_elfnix_create_pthread_key)
624ff6069b8Sluxufan return make_error<StringError>(
625ff6069b8Sluxufan "Attempting to create pthread key in target, but runtime support has "
626ff6069b8Sluxufan "not been loaded yet",
627ff6069b8Sluxufan inconvertibleErrorCode());
628ff6069b8Sluxufan
629ff6069b8Sluxufan Expected<uint64_t> Result(0);
630ff6069b8Sluxufan if (auto Err = ES.callSPSWrapper<SPSExpected<uint64_t>(void)>(
63121a06254SLang Hames orc_rt_elfnix_create_pthread_key, Result))
632ff6069b8Sluxufan return std::move(Err);
633ff6069b8Sluxufan return Result;
634ff6069b8Sluxufan }
635ff6069b8Sluxufan
modifyPassConfig(MaterializationResponsibility & MR,jitlink::LinkGraph & LG,jitlink::PassConfiguration & Config)636b749ef9eSLang Hames void ELFNixPlatform::ELFNixPlatformPlugin::modifyPassConfig(
637b749ef9eSLang Hames MaterializationResponsibility &MR, jitlink::LinkGraph &LG,
638b749ef9eSLang Hames jitlink::PassConfiguration &Config) {
639b749ef9eSLang Hames
640b749ef9eSLang Hames // If the initializer symbol is the __dso_handle symbol then just add
641b749ef9eSLang Hames // the DSO handle support passes.
642b749ef9eSLang Hames if (MR.getInitializerSymbol() == MP.DSOHandleSymbol) {
643b749ef9eSLang Hames addDSOHandleSupportPasses(MR, Config);
644b749ef9eSLang Hames // The DSOHandle materialization unit doesn't require any other
645b749ef9eSLang Hames // support, so we can bail out early.
646b749ef9eSLang Hames return;
647b749ef9eSLang Hames }
648b749ef9eSLang Hames
649b749ef9eSLang Hames // If the object contains initializers then add passes to record them.
650b749ef9eSLang Hames if (MR.getInitializerSymbol())
651b749ef9eSLang Hames addInitializerSupportPasses(MR, Config);
652b749ef9eSLang Hames
653b749ef9eSLang Hames // Add passes for eh-frame and TLV support.
654b749ef9eSLang Hames addEHAndTLVSupportPasses(MR, Config);
655b749ef9eSLang Hames }
656b749ef9eSLang Hames
657b749ef9eSLang Hames ObjectLinkingLayer::Plugin::SyntheticSymbolDependenciesMap
getSyntheticSymbolDependencies(MaterializationResponsibility & MR)658b749ef9eSLang Hames ELFNixPlatform::ELFNixPlatformPlugin::getSyntheticSymbolDependencies(
659b749ef9eSLang Hames MaterializationResponsibility &MR) {
660b749ef9eSLang Hames std::lock_guard<std::mutex> Lock(PluginMutex);
661b749ef9eSLang Hames auto I = InitSymbolDeps.find(&MR);
662b749ef9eSLang Hames if (I != InitSymbolDeps.end()) {
663b749ef9eSLang Hames SyntheticSymbolDependenciesMap Result;
664b749ef9eSLang Hames Result[MR.getInitializerSymbol()] = std::move(I->second);
665b749ef9eSLang Hames InitSymbolDeps.erase(&MR);
666b749ef9eSLang Hames return Result;
667b749ef9eSLang Hames }
668b749ef9eSLang Hames return SyntheticSymbolDependenciesMap();
669b749ef9eSLang Hames }
670b749ef9eSLang Hames
addInitializerSupportPasses(MaterializationResponsibility & MR,jitlink::PassConfiguration & Config)671b749ef9eSLang Hames void ELFNixPlatform::ELFNixPlatformPlugin::addInitializerSupportPasses(
672b749ef9eSLang Hames MaterializationResponsibility &MR, jitlink::PassConfiguration &Config) {
673b749ef9eSLang Hames
674b749ef9eSLang Hames /// Preserve init sections.
675b749ef9eSLang Hames Config.PrePrunePasses.push_back([this, &MR](jitlink::LinkGraph &G) -> Error {
676b749ef9eSLang Hames if (auto Err = preserveInitSections(G, MR))
677b749ef9eSLang Hames return Err;
678b749ef9eSLang Hames return Error::success();
679b749ef9eSLang Hames });
680b749ef9eSLang Hames
681b749ef9eSLang Hames Config.PostFixupPasses.push_back(
682b749ef9eSLang Hames [this, &JD = MR.getTargetJITDylib()](jitlink::LinkGraph &G) {
683b749ef9eSLang Hames return registerInitSections(G, JD);
684b749ef9eSLang Hames });
685b749ef9eSLang Hames }
686b749ef9eSLang Hames
addDSOHandleSupportPasses(MaterializationResponsibility & MR,jitlink::PassConfiguration & Config)687b749ef9eSLang Hames void ELFNixPlatform::ELFNixPlatformPlugin::addDSOHandleSupportPasses(
688b749ef9eSLang Hames MaterializationResponsibility &MR, jitlink::PassConfiguration &Config) {
689b749ef9eSLang Hames
690b749ef9eSLang Hames Config.PostAllocationPasses.push_back([this, &JD = MR.getTargetJITDylib()](
691b749ef9eSLang Hames jitlink::LinkGraph &G) -> Error {
692b749ef9eSLang Hames auto I = llvm::find_if(G.defined_symbols(), [this](jitlink::Symbol *Sym) {
693b749ef9eSLang Hames return Sym->getName() == *MP.DSOHandleSymbol;
694b749ef9eSLang Hames });
695b749ef9eSLang Hames assert(I != G.defined_symbols().end() && "Missing DSO handle symbol");
696b749ef9eSLang Hames {
697b749ef9eSLang Hames std::lock_guard<std::mutex> Lock(MP.PlatformMutex);
698118e953bSLang Hames auto HandleAddr = (*I)->getAddress();
699b749ef9eSLang Hames MP.HandleAddrToJITDylib[HandleAddr] = &JD;
700b749ef9eSLang Hames assert(!MP.InitSeqs.count(&JD) && "InitSeq entry for JD already exists");
701ef391df2SLang Hames MP.InitSeqs.insert(std::make_pair(
702118e953bSLang Hames &JD, ELFNixJITDylibInitializers(JD.getName(), HandleAddr)));
703b749ef9eSLang Hames }
704b749ef9eSLang Hames return Error::success();
705b749ef9eSLang Hames });
706b749ef9eSLang Hames }
707b749ef9eSLang Hames
addEHAndTLVSupportPasses(MaterializationResponsibility & MR,jitlink::PassConfiguration & Config)708b749ef9eSLang Hames void ELFNixPlatform::ELFNixPlatformPlugin::addEHAndTLVSupportPasses(
709b749ef9eSLang Hames MaterializationResponsibility &MR, jitlink::PassConfiguration &Config) {
710b749ef9eSLang Hames
711b749ef9eSLang Hames // Insert TLV lowering at the start of the PostPrunePasses, since we want
712b749ef9eSLang Hames // it to run before GOT/PLT lowering.
713ff6069b8Sluxufan
714ff6069b8Sluxufan // TODO: Check that before the fixTLVSectionsAndEdges pass, the GOT/PLT build
715ff6069b8Sluxufan // pass has done. Because the TLS descriptor need to be allocate in GOT.
716ff6069b8Sluxufan Config.PostPrunePasses.push_back(
717b749ef9eSLang Hames [this, &JD = MR.getTargetJITDylib()](jitlink::LinkGraph &G) {
718b749ef9eSLang Hames return fixTLVSectionsAndEdges(G, JD);
719b749ef9eSLang Hames });
720b749ef9eSLang Hames
721b749ef9eSLang Hames // Add a pass to register the final addresses of the eh-frame and TLV sections
722b749ef9eSLang Hames // with the runtime.
723b749ef9eSLang Hames Config.PostFixupPasses.push_back([this](jitlink::LinkGraph &G) -> Error {
724b749ef9eSLang Hames ELFPerObjectSectionsToRegister POSR;
725b749ef9eSLang Hames
726b749ef9eSLang Hames if (auto *EHFrameSection = G.findSectionByName(EHFrameSectionName)) {
727b749ef9eSLang Hames jitlink::SectionRange R(*EHFrameSection);
728b749ef9eSLang Hames if (!R.empty())
729ef391df2SLang Hames POSR.EHFrameSection = {ExecutorAddr(R.getStart()),
730ef391df2SLang Hames ExecutorAddr(R.getEnd())};
731b749ef9eSLang Hames }
732b749ef9eSLang Hames
733b749ef9eSLang Hames // Get a pointer to the thread data section if there is one. It will be used
734b749ef9eSLang Hames // below.
735b749ef9eSLang Hames jitlink::Section *ThreadDataSection =
736b749ef9eSLang Hames G.findSectionByName(ThreadDataSectionName);
737b749ef9eSLang Hames
738b749ef9eSLang Hames // Handle thread BSS section if there is one.
739b749ef9eSLang Hames if (auto *ThreadBSSSection = G.findSectionByName(ThreadBSSSectionName)) {
740b749ef9eSLang Hames // If there's already a thread data section in this graph then merge the
741b749ef9eSLang Hames // thread BSS section content into it, otherwise just treat the thread
742b749ef9eSLang Hames // BSS section as the thread data section.
743b749ef9eSLang Hames if (ThreadDataSection)
744b749ef9eSLang Hames G.mergeSections(*ThreadDataSection, *ThreadBSSSection);
745b749ef9eSLang Hames else
746b749ef9eSLang Hames ThreadDataSection = ThreadBSSSection;
747b749ef9eSLang Hames }
748b749ef9eSLang Hames
749b749ef9eSLang Hames // Having merged thread BSS (if present) and thread data (if present),
750b749ef9eSLang Hames // record the resulting section range.
751b749ef9eSLang Hames if (ThreadDataSection) {
752b749ef9eSLang Hames jitlink::SectionRange R(*ThreadDataSection);
753b749ef9eSLang Hames if (!R.empty())
754ef391df2SLang Hames POSR.ThreadDataSection = {ExecutorAddr(R.getStart()),
755ef391df2SLang Hames ExecutorAddr(R.getEnd())};
756b749ef9eSLang Hames }
757b749ef9eSLang Hames
758ef391df2SLang Hames if (POSR.EHFrameSection.Start || POSR.ThreadDataSection.Start) {
759b749ef9eSLang Hames
760b749ef9eSLang Hames // If we're still bootstrapping the runtime then just record this
761b749ef9eSLang Hames // frame for now.
762b749ef9eSLang Hames if (!MP.RuntimeBootstrapped) {
763b749ef9eSLang Hames std::lock_guard<std::mutex> Lock(MP.PlatformMutex);
764b749ef9eSLang Hames MP.BootstrapPOSRs.push_back(POSR);
765b749ef9eSLang Hames return Error::success();
766b749ef9eSLang Hames }
767b749ef9eSLang Hames
768b749ef9eSLang Hames // Otherwise register it immediately.
769b749ef9eSLang Hames if (auto Err = MP.registerPerObjectSections(POSR))
770b749ef9eSLang Hames return Err;
771b749ef9eSLang Hames }
772b749ef9eSLang Hames
773b749ef9eSLang Hames return Error::success();
774b749ef9eSLang Hames });
775b749ef9eSLang Hames }
776b749ef9eSLang Hames
preserveInitSections(jitlink::LinkGraph & G,MaterializationResponsibility & MR)777b749ef9eSLang Hames Error ELFNixPlatform::ELFNixPlatformPlugin::preserveInitSections(
778b749ef9eSLang Hames jitlink::LinkGraph &G, MaterializationResponsibility &MR) {
779b749ef9eSLang Hames
780b749ef9eSLang Hames JITLinkSymbolSet InitSectionSymbols;
7812be5abb7SPeter S. Housel for (auto &InitSection : G.sections()) {
782b749ef9eSLang Hames // Skip non-init sections.
7832be5abb7SPeter S. Housel if (!isInitializerSection(InitSection.getName()))
784b749ef9eSLang Hames continue;
785b749ef9eSLang Hames
786b749ef9eSLang Hames // Make a pass over live symbols in the section: those blocks are already
787b749ef9eSLang Hames // preserved.
788b749ef9eSLang Hames DenseSet<jitlink::Block *> AlreadyLiveBlocks;
7892be5abb7SPeter S. Housel for (auto &Sym : InitSection.symbols()) {
790b749ef9eSLang Hames auto &B = Sym->getBlock();
791b749ef9eSLang Hames if (Sym->isLive() && Sym->getOffset() == 0 &&
792b749ef9eSLang Hames Sym->getSize() == B.getSize() && !AlreadyLiveBlocks.count(&B)) {
793b749ef9eSLang Hames InitSectionSymbols.insert(Sym);
794b749ef9eSLang Hames AlreadyLiveBlocks.insert(&B);
795b749ef9eSLang Hames }
796b749ef9eSLang Hames }
797b749ef9eSLang Hames
798b749ef9eSLang Hames // Add anonymous symbols to preserve any not-already-preserved blocks.
7992be5abb7SPeter S. Housel for (auto *B : InitSection.blocks())
800b749ef9eSLang Hames if (!AlreadyLiveBlocks.count(B))
801b749ef9eSLang Hames InitSectionSymbols.insert(
802b749ef9eSLang Hames &G.addAnonymousSymbol(*B, 0, B->getSize(), false, true));
803b749ef9eSLang Hames }
804b749ef9eSLang Hames
805b749ef9eSLang Hames if (!InitSectionSymbols.empty()) {
806b749ef9eSLang Hames std::lock_guard<std::mutex> Lock(PluginMutex);
807b749ef9eSLang Hames InitSymbolDeps[&MR] = std::move(InitSectionSymbols);
808b749ef9eSLang Hames }
809b749ef9eSLang Hames
810b749ef9eSLang Hames return Error::success();
811b749ef9eSLang Hames }
812b749ef9eSLang Hames
registerInitSections(jitlink::LinkGraph & G,JITDylib & JD)813b749ef9eSLang Hames Error ELFNixPlatform::ELFNixPlatformPlugin::registerInitSections(
814b749ef9eSLang Hames jitlink::LinkGraph &G, JITDylib &JD) {
815b749ef9eSLang Hames
816b749ef9eSLang Hames SmallVector<jitlink::Section *> InitSections;
817b749ef9eSLang Hames
818b749ef9eSLang Hames LLVM_DEBUG({ dbgs() << "ELFNixPlatform::registerInitSections\n"; });
819b749ef9eSLang Hames
8202be5abb7SPeter S. Housel for (auto &Sec : G.sections()) {
8212be5abb7SPeter S. Housel if (isInitializerSection(Sec.getName())) {
8222be5abb7SPeter S. Housel InitSections.push_back(&Sec);
823b749ef9eSLang Hames }
824b749ef9eSLang Hames }
825b749ef9eSLang Hames
826b749ef9eSLang Hames // Dump the scraped inits.
827b749ef9eSLang Hames LLVM_DEBUG({
828b749ef9eSLang Hames dbgs() << "ELFNixPlatform: Scraped " << G.getName() << " init sections:\n";
829b749ef9eSLang Hames for (auto *Sec : InitSections) {
830b749ef9eSLang Hames jitlink::SectionRange R(*Sec);
831b749ef9eSLang Hames dbgs() << " " << Sec->getName() << ": "
832b749ef9eSLang Hames << formatv("[ {0:x} -- {1:x} ]", R.getStart(), R.getEnd()) << "\n";
833b749ef9eSLang Hames }
834b749ef9eSLang Hames });
835b749ef9eSLang Hames
836b749ef9eSLang Hames return MP.registerInitInfo(JD, InitSections);
837b749ef9eSLang Hames }
838b749ef9eSLang Hames
fixTLVSectionsAndEdges(jitlink::LinkGraph & G,JITDylib & JD)839b749ef9eSLang Hames Error ELFNixPlatform::ELFNixPlatformPlugin::fixTLVSectionsAndEdges(
840b749ef9eSLang Hames jitlink::LinkGraph &G, JITDylib &JD) {
841b749ef9eSLang Hames
842*30b6c51fSSunho Kim for (auto *Sym : G.external_symbols()) {
843ff6069b8Sluxufan if (Sym->getName() == "__tls_get_addr") {
844ff6069b8Sluxufan Sym->setName("___orc_rt_elfnix_tls_get_addr");
845*30b6c51fSSunho Kim } else if (Sym->getName() == "__tlsdesc_resolver") {
846*30b6c51fSSunho Kim Sym->setName("___orc_rt_elfnix_tlsdesc_resolver");
847*30b6c51fSSunho Kim }
848ff6069b8Sluxufan }
849ff6069b8Sluxufan
850ff6069b8Sluxufan auto *TLSInfoEntrySection = G.findSectionByName("$__TLSINFO");
851ff6069b8Sluxufan
852ff6069b8Sluxufan if (TLSInfoEntrySection) {
853ff6069b8Sluxufan Optional<uint64_t> Key;
854ff6069b8Sluxufan {
855ff6069b8Sluxufan std::lock_guard<std::mutex> Lock(MP.PlatformMutex);
856ff6069b8Sluxufan auto I = MP.JITDylibToPThreadKey.find(&JD);
857ff6069b8Sluxufan if (I != MP.JITDylibToPThreadKey.end())
858ff6069b8Sluxufan Key = I->second;
859ff6069b8Sluxufan }
860ff6069b8Sluxufan if (!Key) {
861ff6069b8Sluxufan if (auto KeyOrErr = MP.createPThreadKey())
862ff6069b8Sluxufan Key = *KeyOrErr;
863ff6069b8Sluxufan else
864ff6069b8Sluxufan return KeyOrErr.takeError();
865ff6069b8Sluxufan }
866ff6069b8Sluxufan
867ff6069b8Sluxufan uint64_t PlatformKeyBits =
868ff6069b8Sluxufan support::endian::byte_swap(*Key, G.getEndianness());
869ff6069b8Sluxufan
870ff6069b8Sluxufan for (auto *B : TLSInfoEntrySection->blocks()) {
871ff6069b8Sluxufan // FIXME: The TLS descriptor byte length may different with different
872ff6069b8Sluxufan // ISA
873ff6069b8Sluxufan assert(B->getSize() == (G.getPointerSize() * 2) &&
874ff6069b8Sluxufan "TLS descriptor must be 2 words length");
875ff6069b8Sluxufan auto TLSInfoEntryContent = B->getMutableContent(G);
876ff6069b8Sluxufan memcpy(TLSInfoEntryContent.data(), &PlatformKeyBits, G.getPointerSize());
877ff6069b8Sluxufan }
878ff6069b8Sluxufan }
879b749ef9eSLang Hames
880b749ef9eSLang Hames return Error::success();
881b749ef9eSLang Hames }
882b749ef9eSLang Hames
883b749ef9eSLang Hames } // End namespace orc.
884b749ef9eSLang Hames } // End namespace llvm.
885