xref: /freebsd-src/contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/ELFNixPlatform.cpp (revision 753f127f3ace09432b2baeffd71a308760641a62)
1349cc55cSDimitry Andric //===------ ELFNixPlatform.cpp - Utilities for executing MachO in Orc -----===//
2349cc55cSDimitry Andric //
3349cc55cSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4349cc55cSDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5349cc55cSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6349cc55cSDimitry Andric //
7349cc55cSDimitry Andric //===----------------------------------------------------------------------===//
8349cc55cSDimitry Andric 
9349cc55cSDimitry Andric #include "llvm/ExecutionEngine/Orc/ELFNixPlatform.h"
10349cc55cSDimitry Andric 
11349cc55cSDimitry Andric #include "llvm/BinaryFormat/ELF.h"
12349cc55cSDimitry Andric #include "llvm/ExecutionEngine/JITLink/ELF_x86_64.h"
1381ad6265SDimitry Andric #include "llvm/ExecutionEngine/JITLink/aarch64.h"
14349cc55cSDimitry Andric #include "llvm/ExecutionEngine/JITLink/x86_64.h"
15349cc55cSDimitry Andric #include "llvm/ExecutionEngine/Orc/DebugUtils.h"
16349cc55cSDimitry Andric #include "llvm/ExecutionEngine/Orc/ExecutionUtils.h"
17349cc55cSDimitry Andric #include "llvm/Support/BinaryByteStream.h"
18349cc55cSDimitry Andric #include "llvm/Support/Debug.h"
19349cc55cSDimitry Andric 
20349cc55cSDimitry Andric #define DEBUG_TYPE "orc"
21349cc55cSDimitry Andric 
22349cc55cSDimitry Andric using namespace llvm;
23349cc55cSDimitry Andric using namespace llvm::orc;
24349cc55cSDimitry Andric using namespace llvm::orc::shared;
25349cc55cSDimitry Andric 
26349cc55cSDimitry Andric namespace {
27349cc55cSDimitry Andric 
28349cc55cSDimitry Andric class DSOHandleMaterializationUnit : public MaterializationUnit {
29349cc55cSDimitry Andric public:
30349cc55cSDimitry Andric   DSOHandleMaterializationUnit(ELFNixPlatform &ENP,
31349cc55cSDimitry Andric                                const SymbolStringPtr &DSOHandleSymbol)
320eae32dcSDimitry Andric       : MaterializationUnit(
330eae32dcSDimitry Andric             createDSOHandleSectionInterface(ENP, DSOHandleSymbol)),
34349cc55cSDimitry Andric         ENP(ENP) {}
35349cc55cSDimitry Andric 
36349cc55cSDimitry Andric   StringRef getName() const override { return "DSOHandleMU"; }
37349cc55cSDimitry Andric 
38349cc55cSDimitry Andric   void materialize(std::unique_ptr<MaterializationResponsibility> R) override {
39349cc55cSDimitry Andric     unsigned PointerSize;
40349cc55cSDimitry Andric     support::endianness Endianness;
41349cc55cSDimitry Andric     jitlink::Edge::Kind EdgeKind;
42349cc55cSDimitry Andric     const auto &TT =
43349cc55cSDimitry Andric         ENP.getExecutionSession().getExecutorProcessControl().getTargetTriple();
44349cc55cSDimitry Andric 
45349cc55cSDimitry Andric     switch (TT.getArch()) {
46349cc55cSDimitry Andric     case Triple::x86_64:
47349cc55cSDimitry Andric       PointerSize = 8;
48349cc55cSDimitry Andric       Endianness = support::endianness::little;
49349cc55cSDimitry Andric       EdgeKind = jitlink::x86_64::Pointer64;
50349cc55cSDimitry Andric       break;
5181ad6265SDimitry Andric     case Triple::aarch64:
5281ad6265SDimitry Andric       PointerSize = 8;
5381ad6265SDimitry Andric       Endianness = support::endianness::little;
5481ad6265SDimitry Andric       EdgeKind = jitlink::aarch64::Pointer64;
5581ad6265SDimitry Andric       break;
56349cc55cSDimitry Andric     default:
57349cc55cSDimitry Andric       llvm_unreachable("Unrecognized architecture");
58349cc55cSDimitry Andric     }
59349cc55cSDimitry Andric 
60349cc55cSDimitry Andric     // void *__dso_handle = &__dso_handle;
61349cc55cSDimitry Andric     auto G = std::make_unique<jitlink::LinkGraph>(
62349cc55cSDimitry Andric         "<DSOHandleMU>", TT, PointerSize, Endianness,
63349cc55cSDimitry Andric         jitlink::getGenericEdgeKindName);
64349cc55cSDimitry Andric     auto &DSOHandleSection =
65349cc55cSDimitry Andric         G->createSection(".data.__dso_handle", jitlink::MemProt::Read);
66349cc55cSDimitry Andric     auto &DSOHandleBlock = G->createContentBlock(
6704eeddc0SDimitry Andric         DSOHandleSection, getDSOHandleContent(PointerSize), orc::ExecutorAddr(),
6804eeddc0SDimitry Andric         8, 0);
69349cc55cSDimitry Andric     auto &DSOHandleSymbol = G->addDefinedSymbol(
70349cc55cSDimitry Andric         DSOHandleBlock, 0, *R->getInitializerSymbol(), DSOHandleBlock.getSize(),
71349cc55cSDimitry Andric         jitlink::Linkage::Strong, jitlink::Scope::Default, false, true);
72349cc55cSDimitry Andric     DSOHandleBlock.addEdge(EdgeKind, 0, DSOHandleSymbol, 0);
73349cc55cSDimitry Andric 
74349cc55cSDimitry Andric     ENP.getObjectLinkingLayer().emit(std::move(R), std::move(G));
75349cc55cSDimitry Andric   }
76349cc55cSDimitry Andric 
77349cc55cSDimitry Andric   void discard(const JITDylib &JD, const SymbolStringPtr &Sym) override {}
78349cc55cSDimitry Andric 
79349cc55cSDimitry Andric private:
800eae32dcSDimitry Andric   static MaterializationUnit::Interface
810eae32dcSDimitry Andric   createDSOHandleSectionInterface(ELFNixPlatform &ENP,
82349cc55cSDimitry Andric                                   const SymbolStringPtr &DSOHandleSymbol) {
83349cc55cSDimitry Andric     SymbolFlagsMap SymbolFlags;
84349cc55cSDimitry Andric     SymbolFlags[DSOHandleSymbol] = JITSymbolFlags::Exported;
850eae32dcSDimitry Andric     return MaterializationUnit::Interface(std::move(SymbolFlags),
860eae32dcSDimitry Andric                                           DSOHandleSymbol);
87349cc55cSDimitry Andric   }
88349cc55cSDimitry Andric 
89349cc55cSDimitry Andric   ArrayRef<char> getDSOHandleContent(size_t PointerSize) {
90349cc55cSDimitry Andric     static const char Content[8] = {0};
91349cc55cSDimitry Andric     assert(PointerSize <= sizeof Content);
92349cc55cSDimitry Andric     return {Content, PointerSize};
93349cc55cSDimitry Andric   }
94349cc55cSDimitry Andric 
95349cc55cSDimitry Andric   ELFNixPlatform &ENP;
96349cc55cSDimitry Andric };
97349cc55cSDimitry Andric 
98349cc55cSDimitry Andric StringRef EHFrameSectionName = ".eh_frame";
99349cc55cSDimitry Andric StringRef InitArrayFuncSectionName = ".init_array";
100349cc55cSDimitry Andric 
101349cc55cSDimitry Andric StringRef ThreadBSSSectionName = ".tbss";
102349cc55cSDimitry Andric StringRef ThreadDataSectionName = ".tdata";
103349cc55cSDimitry Andric 
104349cc55cSDimitry Andric } // end anonymous namespace
105349cc55cSDimitry Andric 
106349cc55cSDimitry Andric namespace llvm {
107349cc55cSDimitry Andric namespace orc {
108349cc55cSDimitry Andric 
109349cc55cSDimitry Andric Expected<std::unique_ptr<ELFNixPlatform>>
110349cc55cSDimitry Andric ELFNixPlatform::Create(ExecutionSession &ES,
111349cc55cSDimitry Andric                        ObjectLinkingLayer &ObjLinkingLayer,
112349cc55cSDimitry Andric                        JITDylib &PlatformJD, const char *OrcRuntimePath,
113349cc55cSDimitry Andric                        Optional<SymbolAliasMap> RuntimeAliases) {
114349cc55cSDimitry Andric 
115349cc55cSDimitry Andric   auto &EPC = ES.getExecutorProcessControl();
116349cc55cSDimitry Andric 
117349cc55cSDimitry Andric   // If the target is not supported then bail out immediately.
118349cc55cSDimitry Andric   if (!supportedTarget(EPC.getTargetTriple()))
119349cc55cSDimitry Andric     return make_error<StringError>("Unsupported ELFNixPlatform triple: " +
120349cc55cSDimitry Andric                                        EPC.getTargetTriple().str(),
121349cc55cSDimitry Andric                                    inconvertibleErrorCode());
122349cc55cSDimitry Andric 
123349cc55cSDimitry Andric   // Create default aliases if the caller didn't supply any.
12481ad6265SDimitry Andric   if (!RuntimeAliases) {
12581ad6265SDimitry Andric     auto StandardRuntimeAliases = standardPlatformAliases(ES, PlatformJD);
12681ad6265SDimitry Andric     if (!StandardRuntimeAliases)
12781ad6265SDimitry Andric       return StandardRuntimeAliases.takeError();
12881ad6265SDimitry Andric     RuntimeAliases = std::move(*StandardRuntimeAliases);
12981ad6265SDimitry Andric   }
130349cc55cSDimitry Andric 
131349cc55cSDimitry Andric   // Define the aliases.
132349cc55cSDimitry Andric   if (auto Err = PlatformJD.define(symbolAliases(std::move(*RuntimeAliases))))
133349cc55cSDimitry Andric     return std::move(Err);
134349cc55cSDimitry Andric 
135349cc55cSDimitry Andric   // Add JIT-dispatch function support symbols.
136349cc55cSDimitry Andric   if (auto Err = PlatformJD.define(absoluteSymbols(
137349cc55cSDimitry Andric           {{ES.intern("__orc_rt_jit_dispatch"),
138349cc55cSDimitry Andric             {EPC.getJITDispatchInfo().JITDispatchFunction.getValue(),
139349cc55cSDimitry Andric              JITSymbolFlags::Exported}},
140349cc55cSDimitry Andric            {ES.intern("__orc_rt_jit_dispatch_ctx"),
141349cc55cSDimitry Andric             {EPC.getJITDispatchInfo().JITDispatchContext.getValue(),
142349cc55cSDimitry Andric              JITSymbolFlags::Exported}}})))
143349cc55cSDimitry Andric     return std::move(Err);
144349cc55cSDimitry Andric 
145349cc55cSDimitry Andric   // Create a generator for the ORC runtime archive.
146349cc55cSDimitry Andric   auto OrcRuntimeArchiveGenerator = StaticLibraryDefinitionGenerator::Load(
147349cc55cSDimitry Andric       ObjLinkingLayer, OrcRuntimePath, EPC.getTargetTriple());
148349cc55cSDimitry Andric   if (!OrcRuntimeArchiveGenerator)
149349cc55cSDimitry Andric     return OrcRuntimeArchiveGenerator.takeError();
150349cc55cSDimitry Andric 
151349cc55cSDimitry Andric   // Create the instance.
152349cc55cSDimitry Andric   Error Err = Error::success();
153349cc55cSDimitry Andric   auto P = std::unique_ptr<ELFNixPlatform>(
154349cc55cSDimitry Andric       new ELFNixPlatform(ES, ObjLinkingLayer, PlatformJD,
155349cc55cSDimitry Andric                          std::move(*OrcRuntimeArchiveGenerator), Err));
156349cc55cSDimitry Andric   if (Err)
157349cc55cSDimitry Andric     return std::move(Err);
158349cc55cSDimitry Andric   return std::move(P);
159349cc55cSDimitry Andric }
160349cc55cSDimitry Andric 
161349cc55cSDimitry Andric Error ELFNixPlatform::setupJITDylib(JITDylib &JD) {
162349cc55cSDimitry Andric   return JD.define(
163349cc55cSDimitry Andric       std::make_unique<DSOHandleMaterializationUnit>(*this, DSOHandleSymbol));
164349cc55cSDimitry Andric }
165349cc55cSDimitry Andric 
16604eeddc0SDimitry Andric Error ELFNixPlatform::teardownJITDylib(JITDylib &JD) {
16704eeddc0SDimitry Andric   return Error::success();
16804eeddc0SDimitry Andric }
16904eeddc0SDimitry Andric 
170349cc55cSDimitry Andric Error ELFNixPlatform::notifyAdding(ResourceTracker &RT,
171349cc55cSDimitry Andric                                    const MaterializationUnit &MU) {
172349cc55cSDimitry Andric   auto &JD = RT.getJITDylib();
173349cc55cSDimitry Andric   const auto &InitSym = MU.getInitializerSymbol();
174349cc55cSDimitry Andric   if (!InitSym)
175349cc55cSDimitry Andric     return Error::success();
176349cc55cSDimitry Andric 
177349cc55cSDimitry Andric   RegisteredInitSymbols[&JD].add(InitSym,
178349cc55cSDimitry Andric                                  SymbolLookupFlags::WeaklyReferencedSymbol);
179349cc55cSDimitry Andric   LLVM_DEBUG({
180349cc55cSDimitry Andric     dbgs() << "ELFNixPlatform: Registered init symbol " << *InitSym
181349cc55cSDimitry Andric            << " for MU " << MU.getName() << "\n";
182349cc55cSDimitry Andric   });
183349cc55cSDimitry Andric   return Error::success();
184349cc55cSDimitry Andric }
185349cc55cSDimitry Andric 
186349cc55cSDimitry Andric Error ELFNixPlatform::notifyRemoving(ResourceTracker &RT) {
187349cc55cSDimitry Andric   llvm_unreachable("Not supported yet");
188349cc55cSDimitry Andric }
189349cc55cSDimitry Andric 
190349cc55cSDimitry Andric static void addAliases(ExecutionSession &ES, SymbolAliasMap &Aliases,
191349cc55cSDimitry Andric                        ArrayRef<std::pair<const char *, const char *>> AL) {
192349cc55cSDimitry Andric   for (auto &KV : AL) {
193349cc55cSDimitry Andric     auto AliasName = ES.intern(KV.first);
194349cc55cSDimitry Andric     assert(!Aliases.count(AliasName) && "Duplicate symbol name in alias map");
195349cc55cSDimitry Andric     Aliases[std::move(AliasName)] = {ES.intern(KV.second),
196349cc55cSDimitry Andric                                      JITSymbolFlags::Exported};
197349cc55cSDimitry Andric   }
198349cc55cSDimitry Andric }
199349cc55cSDimitry Andric 
20081ad6265SDimitry Andric Expected<SymbolAliasMap>
20181ad6265SDimitry Andric ELFNixPlatform::standardPlatformAliases(ExecutionSession &ES,
20281ad6265SDimitry Andric                                         JITDylib &PlatformJD) {
203349cc55cSDimitry Andric   SymbolAliasMap Aliases;
204349cc55cSDimitry Andric   addAliases(ES, Aliases, requiredCXXAliases());
205349cc55cSDimitry Andric   addAliases(ES, Aliases, standardRuntimeUtilityAliases());
20681ad6265SDimitry Andric 
20781ad6265SDimitry Andric   // Determine whether or not the libunwind extended-API function for
20881ad6265SDimitry Andric   // dynamically registering an entire .eh_frame section is available.
20981ad6265SDimitry Andric   // If it is not, we assume that libgcc_s is being used, and alias to
21081ad6265SDimitry Andric   // its __register_frame with the same functionality.
21181ad6265SDimitry Andric   auto RTRegisterFrame = ES.intern("__orc_rt_register_eh_frame_section");
21281ad6265SDimitry Andric   auto LibUnwindRegisterFrame = ES.intern("__unw_add_dynamic_eh_frame_section");
21381ad6265SDimitry Andric   auto RTDeregisterFrame = ES.intern("__orc_rt_deregister_eh_frame_section");
21481ad6265SDimitry Andric   auto LibUnwindDeregisterFrame =
21581ad6265SDimitry Andric       ES.intern("__unw_remove_dynamic_eh_frame_section");
21681ad6265SDimitry Andric   auto SM = ES.lookup(makeJITDylibSearchOrder(&PlatformJD),
21781ad6265SDimitry Andric                       SymbolLookupSet()
21881ad6265SDimitry Andric                           .add(LibUnwindRegisterFrame,
21981ad6265SDimitry Andric                                SymbolLookupFlags::WeaklyReferencedSymbol)
22081ad6265SDimitry Andric                           .add(LibUnwindDeregisterFrame,
22181ad6265SDimitry Andric                                SymbolLookupFlags::WeaklyReferencedSymbol));
22281ad6265SDimitry Andric   if (!SM) { // Weak-ref means no "missing symbol" errors, so this must be
22381ad6265SDimitry Andric              // something more serious that we should report.
22481ad6265SDimitry Andric     return SM.takeError();
22581ad6265SDimitry Andric   } else if (SM->size() == 2) {
22681ad6265SDimitry Andric     LLVM_DEBUG({
22781ad6265SDimitry Andric       dbgs() << "Using libunwind " << LibUnwindRegisterFrame
22881ad6265SDimitry Andric              << " for unwind info registration\n";
22981ad6265SDimitry Andric     });
23081ad6265SDimitry Andric     Aliases[std::move(RTRegisterFrame)] = {LibUnwindRegisterFrame,
23181ad6265SDimitry Andric                                            JITSymbolFlags::Exported};
23281ad6265SDimitry Andric     Aliases[std::move(RTDeregisterFrame)] = {LibUnwindDeregisterFrame,
23381ad6265SDimitry Andric                                              JITSymbolFlags::Exported};
23481ad6265SDimitry Andric   } else {
23581ad6265SDimitry Andric     // Since LLVM libunwind is not present, we assume that unwinding
23681ad6265SDimitry Andric     // is provided by libgcc
23781ad6265SDimitry Andric     LLVM_DEBUG({
23881ad6265SDimitry Andric       dbgs() << "Using libgcc __register_frame"
23981ad6265SDimitry Andric              << " for unwind info registration\n";
24081ad6265SDimitry Andric     });
24181ad6265SDimitry Andric     Aliases[std::move(RTRegisterFrame)] = {ES.intern("__register_frame"),
24281ad6265SDimitry Andric                                            JITSymbolFlags::Exported};
24381ad6265SDimitry Andric     Aliases[std::move(RTDeregisterFrame)] = {ES.intern("__deregister_frame"),
24481ad6265SDimitry Andric                                              JITSymbolFlags::Exported};
24581ad6265SDimitry Andric   }
24681ad6265SDimitry Andric 
247349cc55cSDimitry Andric   return Aliases;
248349cc55cSDimitry Andric }
249349cc55cSDimitry Andric 
250349cc55cSDimitry Andric ArrayRef<std::pair<const char *, const char *>>
251349cc55cSDimitry Andric ELFNixPlatform::requiredCXXAliases() {
252349cc55cSDimitry Andric   static const std::pair<const char *, const char *> RequiredCXXAliases[] = {
253349cc55cSDimitry Andric       {"__cxa_atexit", "__orc_rt_elfnix_cxa_atexit"},
254349cc55cSDimitry Andric       {"atexit", "__orc_rt_elfnix_atexit"}};
255349cc55cSDimitry Andric 
256349cc55cSDimitry Andric   return ArrayRef<std::pair<const char *, const char *>>(RequiredCXXAliases);
257349cc55cSDimitry Andric }
258349cc55cSDimitry Andric 
259349cc55cSDimitry Andric ArrayRef<std::pair<const char *, const char *>>
260349cc55cSDimitry Andric ELFNixPlatform::standardRuntimeUtilityAliases() {
261349cc55cSDimitry Andric   static const std::pair<const char *, const char *>
262349cc55cSDimitry Andric       StandardRuntimeUtilityAliases[] = {
263349cc55cSDimitry Andric           {"__orc_rt_run_program", "__orc_rt_elfnix_run_program"},
26481ad6265SDimitry Andric           {"__orc_rt_jit_dlerror", "__orc_rt_elfnix_jit_dlerror"},
26581ad6265SDimitry Andric           {"__orc_rt_jit_dlopen", "__orc_rt_elfnix_jit_dlopen"},
26681ad6265SDimitry Andric           {"__orc_rt_jit_dlclose", "__orc_rt_elfnix_jit_dlclose"},
26781ad6265SDimitry Andric           {"__orc_rt_jit_dlsym", "__orc_rt_elfnix_jit_dlsym"},
268349cc55cSDimitry Andric           {"__orc_rt_log_error", "__orc_rt_log_error_to_stderr"}};
269349cc55cSDimitry Andric 
270349cc55cSDimitry Andric   return ArrayRef<std::pair<const char *, const char *>>(
271349cc55cSDimitry Andric       StandardRuntimeUtilityAliases);
272349cc55cSDimitry Andric }
273349cc55cSDimitry Andric 
274349cc55cSDimitry Andric bool ELFNixPlatform::isInitializerSection(StringRef SecName) {
27581ad6265SDimitry Andric   if (SecName.consume_front(InitArrayFuncSectionName) &&
27681ad6265SDimitry Andric       (SecName.empty() || SecName[0] == '.'))
277349cc55cSDimitry Andric     return true;
278349cc55cSDimitry Andric   return false;
279349cc55cSDimitry Andric }
280349cc55cSDimitry Andric 
281349cc55cSDimitry Andric bool ELFNixPlatform::supportedTarget(const Triple &TT) {
282349cc55cSDimitry Andric   switch (TT.getArch()) {
283349cc55cSDimitry Andric   case Triple::x86_64:
28481ad6265SDimitry Andric   case Triple::aarch64:
285349cc55cSDimitry Andric     return true;
286349cc55cSDimitry Andric   default:
287349cc55cSDimitry Andric     return false;
288349cc55cSDimitry Andric   }
289349cc55cSDimitry Andric }
290349cc55cSDimitry Andric 
291349cc55cSDimitry Andric ELFNixPlatform::ELFNixPlatform(
292349cc55cSDimitry Andric     ExecutionSession &ES, ObjectLinkingLayer &ObjLinkingLayer,
293349cc55cSDimitry Andric     JITDylib &PlatformJD,
294349cc55cSDimitry Andric     std::unique_ptr<DefinitionGenerator> OrcRuntimeGenerator, Error &Err)
295349cc55cSDimitry Andric     : ES(ES), ObjLinkingLayer(ObjLinkingLayer),
296349cc55cSDimitry Andric       DSOHandleSymbol(ES.intern("__dso_handle")) {
297349cc55cSDimitry Andric   ErrorAsOutParameter _(&Err);
298349cc55cSDimitry Andric 
299349cc55cSDimitry Andric   ObjLinkingLayer.addPlugin(std::make_unique<ELFNixPlatformPlugin>(*this));
300349cc55cSDimitry Andric 
301349cc55cSDimitry Andric   PlatformJD.addGenerator(std::move(OrcRuntimeGenerator));
302349cc55cSDimitry Andric 
303349cc55cSDimitry Andric   // PlatformJD hasn't been 'set-up' by the platform yet (since we're creating
304349cc55cSDimitry Andric   // the platform now), so set it up.
305349cc55cSDimitry Andric   if (auto E2 = setupJITDylib(PlatformJD)) {
306349cc55cSDimitry Andric     Err = std::move(E2);
307349cc55cSDimitry Andric     return;
308349cc55cSDimitry Andric   }
309349cc55cSDimitry Andric 
310349cc55cSDimitry Andric   RegisteredInitSymbols[&PlatformJD].add(
311349cc55cSDimitry Andric       DSOHandleSymbol, SymbolLookupFlags::WeaklyReferencedSymbol);
312349cc55cSDimitry Andric 
313349cc55cSDimitry Andric   // Associate wrapper function tags with JIT-side function implementations.
314349cc55cSDimitry Andric   if (auto E2 = associateRuntimeSupportFunctions(PlatformJD)) {
315349cc55cSDimitry Andric     Err = std::move(E2);
316349cc55cSDimitry Andric     return;
317349cc55cSDimitry Andric   }
318349cc55cSDimitry Andric 
319349cc55cSDimitry Andric   // Lookup addresses of runtime functions callable by the platform,
320349cc55cSDimitry Andric   // call the platform bootstrap function to initialize the platform-state
321349cc55cSDimitry Andric   // object in the executor.
322349cc55cSDimitry Andric   if (auto E2 = bootstrapELFNixRuntime(PlatformJD)) {
323349cc55cSDimitry Andric     Err = std::move(E2);
324349cc55cSDimitry Andric     return;
325349cc55cSDimitry Andric   }
326349cc55cSDimitry Andric }
327349cc55cSDimitry Andric 
328349cc55cSDimitry Andric Error ELFNixPlatform::associateRuntimeSupportFunctions(JITDylib &PlatformJD) {
329349cc55cSDimitry Andric   ExecutionSession::JITDispatchHandlerAssociationMap WFs;
330349cc55cSDimitry Andric 
331349cc55cSDimitry Andric   using GetInitializersSPSSig =
332349cc55cSDimitry Andric       SPSExpected<SPSELFNixJITDylibInitializerSequence>(SPSString);
333349cc55cSDimitry Andric   WFs[ES.intern("__orc_rt_elfnix_get_initializers_tag")] =
334349cc55cSDimitry Andric       ES.wrapAsyncWithSPS<GetInitializersSPSSig>(
335349cc55cSDimitry Andric           this, &ELFNixPlatform::rt_getInitializers);
336349cc55cSDimitry Andric 
337349cc55cSDimitry Andric   using GetDeinitializersSPSSig =
338349cc55cSDimitry Andric       SPSExpected<SPSELFJITDylibDeinitializerSequence>(SPSExecutorAddr);
339349cc55cSDimitry Andric   WFs[ES.intern("__orc_rt_elfnix_get_deinitializers_tag")] =
340349cc55cSDimitry Andric       ES.wrapAsyncWithSPS<GetDeinitializersSPSSig>(
341349cc55cSDimitry Andric           this, &ELFNixPlatform::rt_getDeinitializers);
342349cc55cSDimitry Andric 
343349cc55cSDimitry Andric   using LookupSymbolSPSSig =
344349cc55cSDimitry Andric       SPSExpected<SPSExecutorAddr>(SPSExecutorAddr, SPSString);
345349cc55cSDimitry Andric   WFs[ES.intern("__orc_rt_elfnix_symbol_lookup_tag")] =
346349cc55cSDimitry Andric       ES.wrapAsyncWithSPS<LookupSymbolSPSSig>(this,
347349cc55cSDimitry Andric                                               &ELFNixPlatform::rt_lookupSymbol);
348349cc55cSDimitry Andric 
349349cc55cSDimitry Andric   return ES.registerJITDispatchHandlers(PlatformJD, std::move(WFs));
350349cc55cSDimitry Andric }
351349cc55cSDimitry Andric 
352349cc55cSDimitry Andric void ELFNixPlatform::getInitializersBuildSequencePhase(
353349cc55cSDimitry Andric     SendInitializerSequenceFn SendResult, JITDylib &JD,
354349cc55cSDimitry Andric     std::vector<JITDylibSP> DFSLinkOrder) {
355349cc55cSDimitry Andric   ELFNixJITDylibInitializerSequence FullInitSeq;
356349cc55cSDimitry Andric   {
357349cc55cSDimitry Andric     std::lock_guard<std::mutex> Lock(PlatformMutex);
358349cc55cSDimitry Andric     for (auto &InitJD : reverse(DFSLinkOrder)) {
359349cc55cSDimitry Andric       LLVM_DEBUG({
360349cc55cSDimitry Andric         dbgs() << "ELFNixPlatform: Appending inits for \"" << InitJD->getName()
361349cc55cSDimitry Andric                << "\" to sequence\n";
362349cc55cSDimitry Andric       });
363349cc55cSDimitry Andric       auto ISItr = InitSeqs.find(InitJD.get());
364349cc55cSDimitry Andric       if (ISItr != InitSeqs.end()) {
365349cc55cSDimitry Andric         FullInitSeq.emplace_back(std::move(ISItr->second));
366349cc55cSDimitry Andric         InitSeqs.erase(ISItr);
367349cc55cSDimitry Andric       }
368349cc55cSDimitry Andric     }
369349cc55cSDimitry Andric   }
370349cc55cSDimitry Andric 
371349cc55cSDimitry Andric   SendResult(std::move(FullInitSeq));
372349cc55cSDimitry Andric }
373349cc55cSDimitry Andric 
374349cc55cSDimitry Andric void ELFNixPlatform::getInitializersLookupPhase(
375349cc55cSDimitry Andric     SendInitializerSequenceFn SendResult, JITDylib &JD) {
376349cc55cSDimitry Andric 
377349cc55cSDimitry Andric   auto DFSLinkOrder = JD.getDFSLinkOrder();
37804eeddc0SDimitry Andric   if (!DFSLinkOrder) {
37904eeddc0SDimitry Andric     SendResult(DFSLinkOrder.takeError());
38004eeddc0SDimitry Andric     return;
38104eeddc0SDimitry Andric   }
38204eeddc0SDimitry Andric 
383349cc55cSDimitry Andric   DenseMap<JITDylib *, SymbolLookupSet> NewInitSymbols;
384349cc55cSDimitry Andric   ES.runSessionLocked([&]() {
38504eeddc0SDimitry Andric     for (auto &InitJD : *DFSLinkOrder) {
386349cc55cSDimitry Andric       auto RISItr = RegisteredInitSymbols.find(InitJD.get());
387349cc55cSDimitry Andric       if (RISItr != RegisteredInitSymbols.end()) {
388349cc55cSDimitry Andric         NewInitSymbols[InitJD.get()] = std::move(RISItr->second);
389349cc55cSDimitry Andric         RegisteredInitSymbols.erase(RISItr);
390349cc55cSDimitry Andric       }
391349cc55cSDimitry Andric     }
392349cc55cSDimitry Andric   });
393349cc55cSDimitry Andric 
394349cc55cSDimitry Andric   // If there are no further init symbols to look up then move on to the next
395349cc55cSDimitry Andric   // phase.
396349cc55cSDimitry Andric   if (NewInitSymbols.empty()) {
397349cc55cSDimitry Andric     getInitializersBuildSequencePhase(std::move(SendResult), JD,
39804eeddc0SDimitry Andric                                       std::move(*DFSLinkOrder));
399349cc55cSDimitry Andric     return;
400349cc55cSDimitry Andric   }
401349cc55cSDimitry Andric 
402349cc55cSDimitry Andric   // Otherwise issue a lookup and re-run this phase when it completes.
403349cc55cSDimitry Andric   lookupInitSymbolsAsync(
404349cc55cSDimitry Andric       [this, SendResult = std::move(SendResult), &JD](Error Err) mutable {
405349cc55cSDimitry Andric         if (Err)
406349cc55cSDimitry Andric           SendResult(std::move(Err));
407349cc55cSDimitry Andric         else
408349cc55cSDimitry Andric           getInitializersLookupPhase(std::move(SendResult), JD);
409349cc55cSDimitry Andric       },
410349cc55cSDimitry Andric       ES, std::move(NewInitSymbols));
411349cc55cSDimitry Andric }
412349cc55cSDimitry Andric 
413349cc55cSDimitry Andric void ELFNixPlatform::rt_getInitializers(SendInitializerSequenceFn SendResult,
414349cc55cSDimitry Andric                                         StringRef JDName) {
415349cc55cSDimitry Andric   LLVM_DEBUG({
416349cc55cSDimitry Andric     dbgs() << "ELFNixPlatform::rt_getInitializers(\"" << JDName << "\")\n";
417349cc55cSDimitry Andric   });
418349cc55cSDimitry Andric 
419349cc55cSDimitry Andric   JITDylib *JD = ES.getJITDylibByName(JDName);
420349cc55cSDimitry Andric   if (!JD) {
421349cc55cSDimitry Andric     LLVM_DEBUG({
422349cc55cSDimitry Andric       dbgs() << "  No such JITDylib \"" << JDName << "\". Sending error.\n";
423349cc55cSDimitry Andric     });
424349cc55cSDimitry Andric     SendResult(make_error<StringError>("No JITDylib named " + JDName,
425349cc55cSDimitry Andric                                        inconvertibleErrorCode()));
426349cc55cSDimitry Andric     return;
427349cc55cSDimitry Andric   }
428349cc55cSDimitry Andric 
429349cc55cSDimitry Andric   getInitializersLookupPhase(std::move(SendResult), *JD);
430349cc55cSDimitry Andric }
431349cc55cSDimitry Andric 
432349cc55cSDimitry Andric void ELFNixPlatform::rt_getDeinitializers(
433349cc55cSDimitry Andric     SendDeinitializerSequenceFn SendResult, ExecutorAddr Handle) {
434349cc55cSDimitry Andric   LLVM_DEBUG({
435349cc55cSDimitry Andric     dbgs() << "ELFNixPlatform::rt_getDeinitializers(\""
436349cc55cSDimitry Andric            << formatv("{0:x}", Handle.getValue()) << "\")\n";
437349cc55cSDimitry Andric   });
438349cc55cSDimitry Andric 
439349cc55cSDimitry Andric   JITDylib *JD = nullptr;
440349cc55cSDimitry Andric 
441349cc55cSDimitry Andric   {
442349cc55cSDimitry Andric     std::lock_guard<std::mutex> Lock(PlatformMutex);
44304eeddc0SDimitry Andric     auto I = HandleAddrToJITDylib.find(Handle);
444349cc55cSDimitry Andric     if (I != HandleAddrToJITDylib.end())
445349cc55cSDimitry Andric       JD = I->second;
446349cc55cSDimitry Andric   }
447349cc55cSDimitry Andric 
448349cc55cSDimitry Andric   if (!JD) {
449349cc55cSDimitry Andric     LLVM_DEBUG({
450349cc55cSDimitry Andric       dbgs() << "  No JITDylib for handle "
451349cc55cSDimitry Andric              << formatv("{0:x}", Handle.getValue()) << "\n";
452349cc55cSDimitry Andric     });
453349cc55cSDimitry Andric     SendResult(make_error<StringError>("No JITDylib associated with handle " +
454349cc55cSDimitry Andric                                            formatv("{0:x}", Handle.getValue()),
455349cc55cSDimitry Andric                                        inconvertibleErrorCode()));
456349cc55cSDimitry Andric     return;
457349cc55cSDimitry Andric   }
458349cc55cSDimitry Andric 
459349cc55cSDimitry Andric   SendResult(ELFNixJITDylibDeinitializerSequence());
460349cc55cSDimitry Andric }
461349cc55cSDimitry Andric 
462349cc55cSDimitry Andric void ELFNixPlatform::rt_lookupSymbol(SendSymbolAddressFn SendResult,
463349cc55cSDimitry Andric                                      ExecutorAddr Handle,
464349cc55cSDimitry Andric                                      StringRef SymbolName) {
465349cc55cSDimitry Andric   LLVM_DEBUG({
466349cc55cSDimitry Andric     dbgs() << "ELFNixPlatform::rt_lookupSymbol(\""
467349cc55cSDimitry Andric            << formatv("{0:x}", Handle.getValue()) << "\")\n";
468349cc55cSDimitry Andric   });
469349cc55cSDimitry Andric 
470349cc55cSDimitry Andric   JITDylib *JD = nullptr;
471349cc55cSDimitry Andric 
472349cc55cSDimitry Andric   {
473349cc55cSDimitry Andric     std::lock_guard<std::mutex> Lock(PlatformMutex);
47404eeddc0SDimitry Andric     auto I = HandleAddrToJITDylib.find(Handle);
475349cc55cSDimitry Andric     if (I != HandleAddrToJITDylib.end())
476349cc55cSDimitry Andric       JD = I->second;
477349cc55cSDimitry Andric   }
478349cc55cSDimitry Andric 
479349cc55cSDimitry Andric   if (!JD) {
480349cc55cSDimitry Andric     LLVM_DEBUG({
481349cc55cSDimitry Andric       dbgs() << "  No JITDylib for handle "
482349cc55cSDimitry Andric              << formatv("{0:x}", Handle.getValue()) << "\n";
483349cc55cSDimitry Andric     });
484349cc55cSDimitry Andric     SendResult(make_error<StringError>("No JITDylib associated with handle " +
485349cc55cSDimitry Andric                                            formatv("{0:x}", Handle.getValue()),
486349cc55cSDimitry Andric                                        inconvertibleErrorCode()));
487349cc55cSDimitry Andric     return;
488349cc55cSDimitry Andric   }
489349cc55cSDimitry Andric 
490349cc55cSDimitry Andric   // Use functor class to work around XL build compiler issue on AIX.
491349cc55cSDimitry Andric   class RtLookupNotifyComplete {
492349cc55cSDimitry Andric   public:
493349cc55cSDimitry Andric     RtLookupNotifyComplete(SendSymbolAddressFn &&SendResult)
494349cc55cSDimitry Andric         : SendResult(std::move(SendResult)) {}
495349cc55cSDimitry Andric     void operator()(Expected<SymbolMap> Result) {
496349cc55cSDimitry Andric       if (Result) {
497349cc55cSDimitry Andric         assert(Result->size() == 1 && "Unexpected result map count");
498349cc55cSDimitry Andric         SendResult(ExecutorAddr(Result->begin()->second.getAddress()));
499349cc55cSDimitry Andric       } else {
500349cc55cSDimitry Andric         SendResult(Result.takeError());
501349cc55cSDimitry Andric       }
502349cc55cSDimitry Andric     }
503349cc55cSDimitry Andric 
504349cc55cSDimitry Andric   private:
505349cc55cSDimitry Andric     SendSymbolAddressFn SendResult;
506349cc55cSDimitry Andric   };
507349cc55cSDimitry Andric 
508349cc55cSDimitry Andric   ES.lookup(
509349cc55cSDimitry Andric       LookupKind::DLSym, {{JD, JITDylibLookupFlags::MatchExportedSymbolsOnly}},
510349cc55cSDimitry Andric       SymbolLookupSet(ES.intern(SymbolName)), SymbolState::Ready,
511349cc55cSDimitry Andric       RtLookupNotifyComplete(std::move(SendResult)), NoDependenciesToRegister);
512349cc55cSDimitry Andric }
513349cc55cSDimitry Andric 
514349cc55cSDimitry Andric Error ELFNixPlatform::bootstrapELFNixRuntime(JITDylib &PlatformJD) {
515349cc55cSDimitry Andric 
516349cc55cSDimitry Andric   std::pair<const char *, ExecutorAddr *> Symbols[] = {
517349cc55cSDimitry Andric       {"__orc_rt_elfnix_platform_bootstrap", &orc_rt_elfnix_platform_bootstrap},
518349cc55cSDimitry Andric       {"__orc_rt_elfnix_platform_shutdown", &orc_rt_elfnix_platform_shutdown},
519349cc55cSDimitry Andric       {"__orc_rt_elfnix_register_object_sections",
520349cc55cSDimitry Andric        &orc_rt_elfnix_register_object_sections},
521349cc55cSDimitry Andric       {"__orc_rt_elfnix_create_pthread_key",
522349cc55cSDimitry Andric        &orc_rt_elfnix_create_pthread_key}};
523349cc55cSDimitry Andric 
524349cc55cSDimitry Andric   SymbolLookupSet RuntimeSymbols;
525349cc55cSDimitry Andric   std::vector<std::pair<SymbolStringPtr, ExecutorAddr *>> AddrsToRecord;
526349cc55cSDimitry Andric   for (const auto &KV : Symbols) {
527349cc55cSDimitry Andric     auto Name = ES.intern(KV.first);
528349cc55cSDimitry Andric     RuntimeSymbols.add(Name);
529349cc55cSDimitry Andric     AddrsToRecord.push_back({std::move(Name), KV.second});
530349cc55cSDimitry Andric   }
531349cc55cSDimitry Andric 
532349cc55cSDimitry Andric   auto RuntimeSymbolAddrs = ES.lookup(
533349cc55cSDimitry Andric       {{&PlatformJD, JITDylibLookupFlags::MatchAllSymbols}}, RuntimeSymbols);
534349cc55cSDimitry Andric   if (!RuntimeSymbolAddrs)
535349cc55cSDimitry Andric     return RuntimeSymbolAddrs.takeError();
536349cc55cSDimitry Andric 
537349cc55cSDimitry Andric   for (const auto &KV : AddrsToRecord) {
538349cc55cSDimitry Andric     auto &Name = KV.first;
539349cc55cSDimitry Andric     assert(RuntimeSymbolAddrs->count(Name) && "Missing runtime symbol?");
540349cc55cSDimitry Andric     KV.second->setValue((*RuntimeSymbolAddrs)[Name].getAddress());
541349cc55cSDimitry Andric   }
542349cc55cSDimitry Andric 
543349cc55cSDimitry Andric   auto PJDDSOHandle = ES.lookup(
544349cc55cSDimitry Andric       {{&PlatformJD, JITDylibLookupFlags::MatchAllSymbols}}, DSOHandleSymbol);
545349cc55cSDimitry Andric   if (!PJDDSOHandle)
546349cc55cSDimitry Andric     return PJDDSOHandle.takeError();
547349cc55cSDimitry Andric 
548349cc55cSDimitry Andric   if (auto Err = ES.callSPSWrapper<void(uint64_t)>(
549349cc55cSDimitry Andric           orc_rt_elfnix_platform_bootstrap, PJDDSOHandle->getAddress()))
550349cc55cSDimitry Andric     return Err;
551349cc55cSDimitry Andric 
552349cc55cSDimitry Andric   // FIXME: Ordering is fuzzy here. We're probably best off saying
553349cc55cSDimitry Andric   // "behavior is undefined if code that uses the runtime is added before
554349cc55cSDimitry Andric   // the platform constructor returns", then move all this to the constructor.
555349cc55cSDimitry Andric   RuntimeBootstrapped = true;
556349cc55cSDimitry Andric   std::vector<ELFPerObjectSectionsToRegister> DeferredPOSRs;
557349cc55cSDimitry Andric   {
558349cc55cSDimitry Andric     std::lock_guard<std::mutex> Lock(PlatformMutex);
559349cc55cSDimitry Andric     DeferredPOSRs = std::move(BootstrapPOSRs);
560349cc55cSDimitry Andric   }
561349cc55cSDimitry Andric 
562349cc55cSDimitry Andric   for (auto &D : DeferredPOSRs)
563349cc55cSDimitry Andric     if (auto Err = registerPerObjectSections(D))
564349cc55cSDimitry Andric       return Err;
565349cc55cSDimitry Andric 
566349cc55cSDimitry Andric   return Error::success();
567349cc55cSDimitry Andric }
568349cc55cSDimitry Andric 
569349cc55cSDimitry Andric Error ELFNixPlatform::registerInitInfo(
570349cc55cSDimitry Andric     JITDylib &JD, ArrayRef<jitlink::Section *> InitSections) {
571349cc55cSDimitry Andric 
572349cc55cSDimitry Andric   std::unique_lock<std::mutex> Lock(PlatformMutex);
573349cc55cSDimitry Andric 
574349cc55cSDimitry Andric   ELFNixJITDylibInitializers *InitSeq = nullptr;
575349cc55cSDimitry Andric   {
576349cc55cSDimitry Andric     auto I = InitSeqs.find(&JD);
577349cc55cSDimitry Andric     if (I == InitSeqs.end()) {
578349cc55cSDimitry Andric       // If there's no init sequence entry yet then we need to look up the
579349cc55cSDimitry Andric       // header symbol to force creation of one.
580349cc55cSDimitry Andric       Lock.unlock();
581349cc55cSDimitry Andric 
582349cc55cSDimitry Andric       auto SearchOrder =
583349cc55cSDimitry Andric           JD.withLinkOrderDo([](const JITDylibSearchOrder &SO) { return SO; });
584349cc55cSDimitry Andric       if (auto Err = ES.lookup(SearchOrder, DSOHandleSymbol).takeError())
585349cc55cSDimitry Andric         return Err;
586349cc55cSDimitry Andric 
587349cc55cSDimitry Andric       Lock.lock();
588349cc55cSDimitry Andric       I = InitSeqs.find(&JD);
589349cc55cSDimitry Andric       assert(I != InitSeqs.end() &&
590349cc55cSDimitry Andric              "Entry missing after header symbol lookup?");
591349cc55cSDimitry Andric     }
592349cc55cSDimitry Andric     InitSeq = &I->second;
593349cc55cSDimitry Andric   }
594349cc55cSDimitry Andric 
595349cc55cSDimitry Andric   for (auto *Sec : InitSections) {
596349cc55cSDimitry Andric     // FIXME: Avoid copy here.
597349cc55cSDimitry Andric     jitlink::SectionRange R(*Sec);
598349cc55cSDimitry Andric     InitSeq->InitSections[Sec->getName()].push_back(
599349cc55cSDimitry Andric         {ExecutorAddr(R.getStart()), ExecutorAddr(R.getEnd())});
600349cc55cSDimitry Andric   }
601349cc55cSDimitry Andric 
602349cc55cSDimitry Andric   return Error::success();
603349cc55cSDimitry Andric }
604349cc55cSDimitry Andric 
605349cc55cSDimitry Andric Error ELFNixPlatform::registerPerObjectSections(
606349cc55cSDimitry Andric     const ELFPerObjectSectionsToRegister &POSR) {
607349cc55cSDimitry Andric 
608349cc55cSDimitry Andric   if (!orc_rt_elfnix_register_object_sections)
609349cc55cSDimitry Andric     return make_error<StringError>("Attempting to register per-object "
610349cc55cSDimitry Andric                                    "sections, but runtime support has not "
611349cc55cSDimitry Andric                                    "been loaded yet",
612349cc55cSDimitry Andric                                    inconvertibleErrorCode());
613349cc55cSDimitry Andric 
614349cc55cSDimitry Andric   Error ErrResult = Error::success();
615349cc55cSDimitry Andric   if (auto Err = ES.callSPSWrapper<shared::SPSError(
616349cc55cSDimitry Andric                      SPSELFPerObjectSectionsToRegister)>(
617349cc55cSDimitry Andric           orc_rt_elfnix_register_object_sections, ErrResult, POSR))
618349cc55cSDimitry Andric     return Err;
619349cc55cSDimitry Andric   return ErrResult;
620349cc55cSDimitry Andric }
621349cc55cSDimitry Andric 
622349cc55cSDimitry Andric Expected<uint64_t> ELFNixPlatform::createPThreadKey() {
623349cc55cSDimitry Andric   if (!orc_rt_elfnix_create_pthread_key)
624349cc55cSDimitry Andric     return make_error<StringError>(
625349cc55cSDimitry Andric         "Attempting to create pthread key in target, but runtime support has "
626349cc55cSDimitry Andric         "not been loaded yet",
627349cc55cSDimitry Andric         inconvertibleErrorCode());
628349cc55cSDimitry Andric 
629349cc55cSDimitry Andric   Expected<uint64_t> Result(0);
630349cc55cSDimitry Andric   if (auto Err = ES.callSPSWrapper<SPSExpected<uint64_t>(void)>(
631349cc55cSDimitry Andric           orc_rt_elfnix_create_pthread_key, Result))
632349cc55cSDimitry Andric     return std::move(Err);
633349cc55cSDimitry Andric   return Result;
634349cc55cSDimitry Andric }
635349cc55cSDimitry Andric 
636349cc55cSDimitry Andric void ELFNixPlatform::ELFNixPlatformPlugin::modifyPassConfig(
637349cc55cSDimitry Andric     MaterializationResponsibility &MR, jitlink::LinkGraph &LG,
638349cc55cSDimitry Andric     jitlink::PassConfiguration &Config) {
639349cc55cSDimitry Andric 
640349cc55cSDimitry Andric   // If the initializer symbol is the __dso_handle symbol then just add
641349cc55cSDimitry Andric   // the DSO handle support passes.
642349cc55cSDimitry Andric   if (MR.getInitializerSymbol() == MP.DSOHandleSymbol) {
643349cc55cSDimitry Andric     addDSOHandleSupportPasses(MR, Config);
644349cc55cSDimitry Andric     // The DSOHandle materialization unit doesn't require any other
645349cc55cSDimitry Andric     // support, so we can bail out early.
646349cc55cSDimitry Andric     return;
647349cc55cSDimitry Andric   }
648349cc55cSDimitry Andric 
649349cc55cSDimitry Andric   // If the object contains initializers then add passes to record them.
650349cc55cSDimitry Andric   if (MR.getInitializerSymbol())
651349cc55cSDimitry Andric     addInitializerSupportPasses(MR, Config);
652349cc55cSDimitry Andric 
653349cc55cSDimitry Andric   // Add passes for eh-frame and TLV support.
654349cc55cSDimitry Andric   addEHAndTLVSupportPasses(MR, Config);
655349cc55cSDimitry Andric }
656349cc55cSDimitry Andric 
657349cc55cSDimitry Andric ObjectLinkingLayer::Plugin::SyntheticSymbolDependenciesMap
658349cc55cSDimitry Andric ELFNixPlatform::ELFNixPlatformPlugin::getSyntheticSymbolDependencies(
659349cc55cSDimitry Andric     MaterializationResponsibility &MR) {
660349cc55cSDimitry Andric   std::lock_guard<std::mutex> Lock(PluginMutex);
661349cc55cSDimitry Andric   auto I = InitSymbolDeps.find(&MR);
662349cc55cSDimitry Andric   if (I != InitSymbolDeps.end()) {
663349cc55cSDimitry Andric     SyntheticSymbolDependenciesMap Result;
664349cc55cSDimitry Andric     Result[MR.getInitializerSymbol()] = std::move(I->second);
665349cc55cSDimitry Andric     InitSymbolDeps.erase(&MR);
666349cc55cSDimitry Andric     return Result;
667349cc55cSDimitry Andric   }
668349cc55cSDimitry Andric   return SyntheticSymbolDependenciesMap();
669349cc55cSDimitry Andric }
670349cc55cSDimitry Andric 
671349cc55cSDimitry Andric void ELFNixPlatform::ELFNixPlatformPlugin::addInitializerSupportPasses(
672349cc55cSDimitry Andric     MaterializationResponsibility &MR, jitlink::PassConfiguration &Config) {
673349cc55cSDimitry Andric 
674349cc55cSDimitry Andric   /// Preserve init sections.
675349cc55cSDimitry Andric   Config.PrePrunePasses.push_back([this, &MR](jitlink::LinkGraph &G) -> Error {
676349cc55cSDimitry Andric     if (auto Err = preserveInitSections(G, MR))
677349cc55cSDimitry Andric       return Err;
678349cc55cSDimitry Andric     return Error::success();
679349cc55cSDimitry Andric   });
680349cc55cSDimitry Andric 
681349cc55cSDimitry Andric   Config.PostFixupPasses.push_back(
682349cc55cSDimitry Andric       [this, &JD = MR.getTargetJITDylib()](jitlink::LinkGraph &G) {
683349cc55cSDimitry Andric         return registerInitSections(G, JD);
684349cc55cSDimitry Andric       });
685349cc55cSDimitry Andric }
686349cc55cSDimitry Andric 
687349cc55cSDimitry Andric void ELFNixPlatform::ELFNixPlatformPlugin::addDSOHandleSupportPasses(
688349cc55cSDimitry Andric     MaterializationResponsibility &MR, jitlink::PassConfiguration &Config) {
689349cc55cSDimitry Andric 
690349cc55cSDimitry Andric   Config.PostAllocationPasses.push_back([this, &JD = MR.getTargetJITDylib()](
691349cc55cSDimitry Andric                                             jitlink::LinkGraph &G) -> Error {
692349cc55cSDimitry Andric     auto I = llvm::find_if(G.defined_symbols(), [this](jitlink::Symbol *Sym) {
693349cc55cSDimitry Andric       return Sym->getName() == *MP.DSOHandleSymbol;
694349cc55cSDimitry Andric     });
695349cc55cSDimitry Andric     assert(I != G.defined_symbols().end() && "Missing DSO handle symbol");
696349cc55cSDimitry Andric     {
697349cc55cSDimitry Andric       std::lock_guard<std::mutex> Lock(MP.PlatformMutex);
69804eeddc0SDimitry Andric       auto HandleAddr = (*I)->getAddress();
699349cc55cSDimitry Andric       MP.HandleAddrToJITDylib[HandleAddr] = &JD;
700349cc55cSDimitry Andric       assert(!MP.InitSeqs.count(&JD) && "InitSeq entry for JD already exists");
701349cc55cSDimitry Andric       MP.InitSeqs.insert(std::make_pair(
70204eeddc0SDimitry Andric           &JD, ELFNixJITDylibInitializers(JD.getName(), HandleAddr)));
703349cc55cSDimitry Andric     }
704349cc55cSDimitry Andric     return Error::success();
705349cc55cSDimitry Andric   });
706349cc55cSDimitry Andric }
707349cc55cSDimitry Andric 
708349cc55cSDimitry Andric void ELFNixPlatform::ELFNixPlatformPlugin::addEHAndTLVSupportPasses(
709349cc55cSDimitry Andric     MaterializationResponsibility &MR, jitlink::PassConfiguration &Config) {
710349cc55cSDimitry Andric 
711349cc55cSDimitry Andric   // Insert TLV lowering at the start of the PostPrunePasses, since we want
712349cc55cSDimitry Andric   // it to run before GOT/PLT lowering.
713349cc55cSDimitry Andric 
714349cc55cSDimitry Andric   // TODO: Check that before the fixTLVSectionsAndEdges pass, the GOT/PLT build
715349cc55cSDimitry Andric   // pass has done. Because the TLS descriptor need to be allocate in GOT.
716349cc55cSDimitry Andric   Config.PostPrunePasses.push_back(
717349cc55cSDimitry Andric       [this, &JD = MR.getTargetJITDylib()](jitlink::LinkGraph &G) {
718349cc55cSDimitry Andric         return fixTLVSectionsAndEdges(G, JD);
719349cc55cSDimitry Andric       });
720349cc55cSDimitry Andric 
721349cc55cSDimitry Andric   // Add a pass to register the final addresses of the eh-frame and TLV sections
722349cc55cSDimitry Andric   // with the runtime.
723349cc55cSDimitry Andric   Config.PostFixupPasses.push_back([this](jitlink::LinkGraph &G) -> Error {
724349cc55cSDimitry Andric     ELFPerObjectSectionsToRegister POSR;
725349cc55cSDimitry Andric 
726349cc55cSDimitry Andric     if (auto *EHFrameSection = G.findSectionByName(EHFrameSectionName)) {
727349cc55cSDimitry Andric       jitlink::SectionRange R(*EHFrameSection);
728349cc55cSDimitry Andric       if (!R.empty())
729349cc55cSDimitry Andric         POSR.EHFrameSection = {ExecutorAddr(R.getStart()),
730349cc55cSDimitry Andric                                ExecutorAddr(R.getEnd())};
731349cc55cSDimitry Andric     }
732349cc55cSDimitry Andric 
733349cc55cSDimitry Andric     // Get a pointer to the thread data section if there is one. It will be used
734349cc55cSDimitry Andric     // below.
735349cc55cSDimitry Andric     jitlink::Section *ThreadDataSection =
736349cc55cSDimitry Andric         G.findSectionByName(ThreadDataSectionName);
737349cc55cSDimitry Andric 
738349cc55cSDimitry Andric     // Handle thread BSS section if there is one.
739349cc55cSDimitry Andric     if (auto *ThreadBSSSection = G.findSectionByName(ThreadBSSSectionName)) {
740349cc55cSDimitry Andric       // If there's already a thread data section in this graph then merge the
741349cc55cSDimitry Andric       // thread BSS section content into it, otherwise just treat the thread
742349cc55cSDimitry Andric       // BSS section as the thread data section.
743349cc55cSDimitry Andric       if (ThreadDataSection)
744349cc55cSDimitry Andric         G.mergeSections(*ThreadDataSection, *ThreadBSSSection);
745349cc55cSDimitry Andric       else
746349cc55cSDimitry Andric         ThreadDataSection = ThreadBSSSection;
747349cc55cSDimitry Andric     }
748349cc55cSDimitry Andric 
749349cc55cSDimitry Andric     // Having merged thread BSS (if present) and thread data (if present),
750349cc55cSDimitry Andric     // record the resulting section range.
751349cc55cSDimitry Andric     if (ThreadDataSection) {
752349cc55cSDimitry Andric       jitlink::SectionRange R(*ThreadDataSection);
753349cc55cSDimitry Andric       if (!R.empty())
754349cc55cSDimitry Andric         POSR.ThreadDataSection = {ExecutorAddr(R.getStart()),
755349cc55cSDimitry Andric                                   ExecutorAddr(R.getEnd())};
756349cc55cSDimitry Andric     }
757349cc55cSDimitry Andric 
758349cc55cSDimitry Andric     if (POSR.EHFrameSection.Start || POSR.ThreadDataSection.Start) {
759349cc55cSDimitry Andric 
760349cc55cSDimitry Andric       // If we're still bootstrapping the runtime then just record this
761349cc55cSDimitry Andric       // frame for now.
762349cc55cSDimitry Andric       if (!MP.RuntimeBootstrapped) {
763349cc55cSDimitry Andric         std::lock_guard<std::mutex> Lock(MP.PlatformMutex);
764349cc55cSDimitry Andric         MP.BootstrapPOSRs.push_back(POSR);
765349cc55cSDimitry Andric         return Error::success();
766349cc55cSDimitry Andric       }
767349cc55cSDimitry Andric 
768349cc55cSDimitry Andric       // Otherwise register it immediately.
769349cc55cSDimitry Andric       if (auto Err = MP.registerPerObjectSections(POSR))
770349cc55cSDimitry Andric         return Err;
771349cc55cSDimitry Andric     }
772349cc55cSDimitry Andric 
773349cc55cSDimitry Andric     return Error::success();
774349cc55cSDimitry Andric   });
775349cc55cSDimitry Andric }
776349cc55cSDimitry Andric 
777349cc55cSDimitry Andric Error ELFNixPlatform::ELFNixPlatformPlugin::preserveInitSections(
778349cc55cSDimitry Andric     jitlink::LinkGraph &G, MaterializationResponsibility &MR) {
779349cc55cSDimitry Andric 
780349cc55cSDimitry Andric   JITLinkSymbolSet InitSectionSymbols;
78181ad6265SDimitry Andric   for (auto &InitSection : G.sections()) {
782349cc55cSDimitry Andric     // Skip non-init sections.
78381ad6265SDimitry Andric     if (!isInitializerSection(InitSection.getName()))
784349cc55cSDimitry Andric       continue;
785349cc55cSDimitry Andric 
786349cc55cSDimitry Andric     // Make a pass over live symbols in the section: those blocks are already
787349cc55cSDimitry Andric     // preserved.
788349cc55cSDimitry Andric     DenseSet<jitlink::Block *> AlreadyLiveBlocks;
78981ad6265SDimitry Andric     for (auto &Sym : InitSection.symbols()) {
790349cc55cSDimitry Andric       auto &B = Sym->getBlock();
791349cc55cSDimitry Andric       if (Sym->isLive() && Sym->getOffset() == 0 &&
792349cc55cSDimitry Andric           Sym->getSize() == B.getSize() && !AlreadyLiveBlocks.count(&B)) {
793349cc55cSDimitry Andric         InitSectionSymbols.insert(Sym);
794349cc55cSDimitry Andric         AlreadyLiveBlocks.insert(&B);
795349cc55cSDimitry Andric       }
796349cc55cSDimitry Andric     }
797349cc55cSDimitry Andric 
798349cc55cSDimitry Andric     // Add anonymous symbols to preserve any not-already-preserved blocks.
79981ad6265SDimitry Andric     for (auto *B : InitSection.blocks())
800349cc55cSDimitry Andric       if (!AlreadyLiveBlocks.count(B))
801349cc55cSDimitry Andric         InitSectionSymbols.insert(
802349cc55cSDimitry Andric             &G.addAnonymousSymbol(*B, 0, B->getSize(), false, true));
803349cc55cSDimitry Andric   }
804349cc55cSDimitry Andric 
805349cc55cSDimitry Andric   if (!InitSectionSymbols.empty()) {
806349cc55cSDimitry Andric     std::lock_guard<std::mutex> Lock(PluginMutex);
807349cc55cSDimitry Andric     InitSymbolDeps[&MR] = std::move(InitSectionSymbols);
808349cc55cSDimitry Andric   }
809349cc55cSDimitry Andric 
810349cc55cSDimitry Andric   return Error::success();
811349cc55cSDimitry Andric }
812349cc55cSDimitry Andric 
813349cc55cSDimitry Andric Error ELFNixPlatform::ELFNixPlatformPlugin::registerInitSections(
814349cc55cSDimitry Andric     jitlink::LinkGraph &G, JITDylib &JD) {
815349cc55cSDimitry Andric 
816349cc55cSDimitry Andric   SmallVector<jitlink::Section *> InitSections;
817349cc55cSDimitry Andric 
818349cc55cSDimitry Andric   LLVM_DEBUG({ dbgs() << "ELFNixPlatform::registerInitSections\n"; });
819349cc55cSDimitry Andric 
82081ad6265SDimitry Andric   for (auto &Sec : G.sections()) {
82181ad6265SDimitry Andric     if (isInitializerSection(Sec.getName())) {
82281ad6265SDimitry Andric       InitSections.push_back(&Sec);
823349cc55cSDimitry Andric     }
824349cc55cSDimitry Andric   }
825349cc55cSDimitry Andric 
826349cc55cSDimitry Andric   // Dump the scraped inits.
827349cc55cSDimitry Andric   LLVM_DEBUG({
828349cc55cSDimitry Andric     dbgs() << "ELFNixPlatform: Scraped " << G.getName() << " init sections:\n";
829349cc55cSDimitry Andric     for (auto *Sec : InitSections) {
830349cc55cSDimitry Andric       jitlink::SectionRange R(*Sec);
831349cc55cSDimitry Andric       dbgs() << "  " << Sec->getName() << ": "
832349cc55cSDimitry Andric              << formatv("[ {0:x} -- {1:x} ]", R.getStart(), R.getEnd()) << "\n";
833349cc55cSDimitry Andric     }
834349cc55cSDimitry Andric   });
835349cc55cSDimitry Andric 
836349cc55cSDimitry Andric   return MP.registerInitInfo(JD, InitSections);
837349cc55cSDimitry Andric }
838349cc55cSDimitry Andric 
839349cc55cSDimitry Andric Error ELFNixPlatform::ELFNixPlatformPlugin::fixTLVSectionsAndEdges(
840349cc55cSDimitry Andric     jitlink::LinkGraph &G, JITDylib &JD) {
841349cc55cSDimitry Andric 
842*753f127fSDimitry Andric   for (auto *Sym : G.external_symbols()) {
843349cc55cSDimitry Andric     if (Sym->getName() == "__tls_get_addr") {
844349cc55cSDimitry Andric       Sym->setName("___orc_rt_elfnix_tls_get_addr");
845*753f127fSDimitry Andric     } else if (Sym->getName() == "__tlsdesc_resolver") {
846*753f127fSDimitry Andric       Sym->setName("___orc_rt_elfnix_tlsdesc_resolver");
847*753f127fSDimitry Andric     }
848349cc55cSDimitry Andric   }
849349cc55cSDimitry Andric 
850349cc55cSDimitry Andric   auto *TLSInfoEntrySection = G.findSectionByName("$__TLSINFO");
851349cc55cSDimitry Andric 
852349cc55cSDimitry Andric   if (TLSInfoEntrySection) {
853349cc55cSDimitry Andric     Optional<uint64_t> Key;
854349cc55cSDimitry Andric     {
855349cc55cSDimitry Andric       std::lock_guard<std::mutex> Lock(MP.PlatformMutex);
856349cc55cSDimitry Andric       auto I = MP.JITDylibToPThreadKey.find(&JD);
857349cc55cSDimitry Andric       if (I != MP.JITDylibToPThreadKey.end())
858349cc55cSDimitry Andric         Key = I->second;
859349cc55cSDimitry Andric     }
860349cc55cSDimitry Andric     if (!Key) {
861349cc55cSDimitry Andric       if (auto KeyOrErr = MP.createPThreadKey())
862349cc55cSDimitry Andric         Key = *KeyOrErr;
863349cc55cSDimitry Andric       else
864349cc55cSDimitry Andric         return KeyOrErr.takeError();
865349cc55cSDimitry Andric     }
866349cc55cSDimitry Andric 
867349cc55cSDimitry Andric     uint64_t PlatformKeyBits =
868349cc55cSDimitry Andric         support::endian::byte_swap(*Key, G.getEndianness());
869349cc55cSDimitry Andric 
870349cc55cSDimitry Andric     for (auto *B : TLSInfoEntrySection->blocks()) {
871349cc55cSDimitry Andric       // FIXME: The TLS descriptor byte length may different with different
872349cc55cSDimitry Andric       // ISA
873349cc55cSDimitry Andric       assert(B->getSize() == (G.getPointerSize() * 2) &&
874349cc55cSDimitry Andric              "TLS descriptor must be 2 words length");
875349cc55cSDimitry Andric       auto TLSInfoEntryContent = B->getMutableContent(G);
876349cc55cSDimitry Andric       memcpy(TLSInfoEntryContent.data(), &PlatformKeyBits, G.getPointerSize());
877349cc55cSDimitry Andric     }
878349cc55cSDimitry Andric   }
879349cc55cSDimitry Andric 
880349cc55cSDimitry Andric   return Error::success();
881349cc55cSDimitry Andric }
882349cc55cSDimitry Andric 
883349cc55cSDimitry Andric } // End namespace orc.
884349cc55cSDimitry Andric } // End namespace llvm.
885