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