xref: /freebsd-src/contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/ELFNixPlatform.cpp (revision 5f757f3ff9144b609b3c433dfd370cc6bdc191ad)
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"
14*5f757f3fSDimitry Andric #include "llvm/ExecutionEngine/JITLink/ppc64.h"
15349cc55cSDimitry Andric #include "llvm/ExecutionEngine/JITLink/x86_64.h"
16349cc55cSDimitry Andric #include "llvm/ExecutionEngine/Orc/DebugUtils.h"
17349cc55cSDimitry Andric #include "llvm/ExecutionEngine/Orc/ExecutionUtils.h"
1806c3fb27SDimitry Andric #include "llvm/ExecutionEngine/Orc/Shared/ObjectFormats.h"
19349cc55cSDimitry Andric #include "llvm/Support/BinaryByteStream.h"
20349cc55cSDimitry Andric #include "llvm/Support/Debug.h"
21bdd1243dSDimitry Andric #include <optional>
22349cc55cSDimitry Andric 
23349cc55cSDimitry Andric #define DEBUG_TYPE "orc"
24349cc55cSDimitry Andric 
25349cc55cSDimitry Andric using namespace llvm;
26349cc55cSDimitry Andric using namespace llvm::orc;
27349cc55cSDimitry Andric using namespace llvm::orc::shared;
28349cc55cSDimitry Andric 
29349cc55cSDimitry Andric namespace {
30349cc55cSDimitry Andric 
31349cc55cSDimitry Andric class DSOHandleMaterializationUnit : public MaterializationUnit {
32349cc55cSDimitry Andric public:
DSOHandleMaterializationUnit(ELFNixPlatform & ENP,const SymbolStringPtr & DSOHandleSymbol)33349cc55cSDimitry Andric   DSOHandleMaterializationUnit(ELFNixPlatform &ENP,
34349cc55cSDimitry Andric                                const SymbolStringPtr &DSOHandleSymbol)
350eae32dcSDimitry Andric       : MaterializationUnit(
360eae32dcSDimitry Andric             createDSOHandleSectionInterface(ENP, DSOHandleSymbol)),
37349cc55cSDimitry Andric         ENP(ENP) {}
38349cc55cSDimitry Andric 
getName() const39349cc55cSDimitry Andric   StringRef getName() const override { return "DSOHandleMU"; }
40349cc55cSDimitry Andric 
materialize(std::unique_ptr<MaterializationResponsibility> R)41349cc55cSDimitry Andric   void materialize(std::unique_ptr<MaterializationResponsibility> R) override {
42349cc55cSDimitry Andric     unsigned PointerSize;
43*5f757f3fSDimitry Andric     llvm::endianness Endianness;
44349cc55cSDimitry Andric     jitlink::Edge::Kind EdgeKind;
4506c3fb27SDimitry Andric     const auto &TT = ENP.getExecutionSession().getTargetTriple();
46349cc55cSDimitry Andric 
47349cc55cSDimitry Andric     switch (TT.getArch()) {
48349cc55cSDimitry Andric     case Triple::x86_64:
49349cc55cSDimitry Andric       PointerSize = 8;
50*5f757f3fSDimitry Andric       Endianness = llvm::endianness::little;
51349cc55cSDimitry Andric       EdgeKind = jitlink::x86_64::Pointer64;
52349cc55cSDimitry Andric       break;
5381ad6265SDimitry Andric     case Triple::aarch64:
5481ad6265SDimitry Andric       PointerSize = 8;
55*5f757f3fSDimitry Andric       Endianness = llvm::endianness::little;
5681ad6265SDimitry Andric       EdgeKind = jitlink::aarch64::Pointer64;
5781ad6265SDimitry Andric       break;
58*5f757f3fSDimitry Andric     case Triple::ppc64:
59*5f757f3fSDimitry Andric       PointerSize = 8;
60*5f757f3fSDimitry Andric       Endianness = llvm::endianness::big;
61*5f757f3fSDimitry Andric       EdgeKind = jitlink::ppc64::Pointer64;
62*5f757f3fSDimitry Andric       break;
63*5f757f3fSDimitry Andric     case Triple::ppc64le:
64*5f757f3fSDimitry Andric       PointerSize = 8;
65*5f757f3fSDimitry Andric       Endianness = llvm::endianness::little;
66*5f757f3fSDimitry Andric       EdgeKind = jitlink::ppc64::Pointer64;
67*5f757f3fSDimitry Andric       break;
68349cc55cSDimitry Andric     default:
69349cc55cSDimitry Andric       llvm_unreachable("Unrecognized architecture");
70349cc55cSDimitry Andric     }
71349cc55cSDimitry Andric 
72349cc55cSDimitry Andric     // void *__dso_handle = &__dso_handle;
73349cc55cSDimitry Andric     auto G = std::make_unique<jitlink::LinkGraph>(
74349cc55cSDimitry Andric         "<DSOHandleMU>", TT, PointerSize, Endianness,
75349cc55cSDimitry Andric         jitlink::getGenericEdgeKindName);
76349cc55cSDimitry Andric     auto &DSOHandleSection =
77bdd1243dSDimitry Andric         G->createSection(".data.__dso_handle", MemProt::Read);
78349cc55cSDimitry Andric     auto &DSOHandleBlock = G->createContentBlock(
7904eeddc0SDimitry Andric         DSOHandleSection, getDSOHandleContent(PointerSize), orc::ExecutorAddr(),
8004eeddc0SDimitry Andric         8, 0);
81349cc55cSDimitry Andric     auto &DSOHandleSymbol = G->addDefinedSymbol(
82349cc55cSDimitry Andric         DSOHandleBlock, 0, *R->getInitializerSymbol(), DSOHandleBlock.getSize(),
83349cc55cSDimitry Andric         jitlink::Linkage::Strong, jitlink::Scope::Default, false, true);
84349cc55cSDimitry Andric     DSOHandleBlock.addEdge(EdgeKind, 0, DSOHandleSymbol, 0);
85349cc55cSDimitry Andric 
86349cc55cSDimitry Andric     ENP.getObjectLinkingLayer().emit(std::move(R), std::move(G));
87349cc55cSDimitry Andric   }
88349cc55cSDimitry Andric 
discard(const JITDylib & JD,const SymbolStringPtr & Sym)89349cc55cSDimitry Andric   void discard(const JITDylib &JD, const SymbolStringPtr &Sym) override {}
90349cc55cSDimitry Andric 
91349cc55cSDimitry Andric private:
920eae32dcSDimitry Andric   static MaterializationUnit::Interface
createDSOHandleSectionInterface(ELFNixPlatform & ENP,const SymbolStringPtr & DSOHandleSymbol)930eae32dcSDimitry Andric   createDSOHandleSectionInterface(ELFNixPlatform &ENP,
94349cc55cSDimitry Andric                                   const SymbolStringPtr &DSOHandleSymbol) {
95349cc55cSDimitry Andric     SymbolFlagsMap SymbolFlags;
96349cc55cSDimitry Andric     SymbolFlags[DSOHandleSymbol] = JITSymbolFlags::Exported;
970eae32dcSDimitry Andric     return MaterializationUnit::Interface(std::move(SymbolFlags),
980eae32dcSDimitry Andric                                           DSOHandleSymbol);
99349cc55cSDimitry Andric   }
100349cc55cSDimitry Andric 
getDSOHandleContent(size_t PointerSize)101349cc55cSDimitry Andric   ArrayRef<char> getDSOHandleContent(size_t PointerSize) {
102349cc55cSDimitry Andric     static const char Content[8] = {0};
103349cc55cSDimitry Andric     assert(PointerSize <= sizeof Content);
104349cc55cSDimitry Andric     return {Content, PointerSize};
105349cc55cSDimitry Andric   }
106349cc55cSDimitry Andric 
107349cc55cSDimitry Andric   ELFNixPlatform &ENP;
108349cc55cSDimitry Andric };
109349cc55cSDimitry Andric 
110349cc55cSDimitry Andric } // end anonymous namespace
111349cc55cSDimitry Andric 
112349cc55cSDimitry Andric namespace llvm {
113349cc55cSDimitry Andric namespace orc {
114349cc55cSDimitry Andric 
Create(ExecutionSession & ES,ObjectLinkingLayer & ObjLinkingLayer,JITDylib & PlatformJD,std::unique_ptr<DefinitionGenerator> OrcRuntime,std::optional<SymbolAliasMap> RuntimeAliases)11506c3fb27SDimitry Andric Expected<std::unique_ptr<ELFNixPlatform>> ELFNixPlatform::Create(
11606c3fb27SDimitry Andric     ExecutionSession &ES, ObjectLinkingLayer &ObjLinkingLayer,
11706c3fb27SDimitry Andric     JITDylib &PlatformJD, std::unique_ptr<DefinitionGenerator> OrcRuntime,
118bdd1243dSDimitry Andric     std::optional<SymbolAliasMap> RuntimeAliases) {
119349cc55cSDimitry Andric 
120349cc55cSDimitry Andric   // If the target is not supported then bail out immediately.
12106c3fb27SDimitry Andric   if (!supportedTarget(ES.getTargetTriple()))
122349cc55cSDimitry Andric     return make_error<StringError>("Unsupported ELFNixPlatform triple: " +
12306c3fb27SDimitry Andric                                        ES.getTargetTriple().str(),
124349cc55cSDimitry Andric                                    inconvertibleErrorCode());
125349cc55cSDimitry Andric 
12606c3fb27SDimitry Andric   auto &EPC = ES.getExecutorProcessControl();
12706c3fb27SDimitry Andric 
128349cc55cSDimitry Andric   // Create default aliases if the caller didn't supply any.
12981ad6265SDimitry Andric   if (!RuntimeAliases) {
13081ad6265SDimitry Andric     auto StandardRuntimeAliases = standardPlatformAliases(ES, PlatformJD);
13181ad6265SDimitry Andric     if (!StandardRuntimeAliases)
13281ad6265SDimitry Andric       return StandardRuntimeAliases.takeError();
13381ad6265SDimitry Andric     RuntimeAliases = std::move(*StandardRuntimeAliases);
13481ad6265SDimitry Andric   }
135349cc55cSDimitry Andric 
136349cc55cSDimitry Andric   // Define the aliases.
137349cc55cSDimitry Andric   if (auto Err = PlatformJD.define(symbolAliases(std::move(*RuntimeAliases))))
138349cc55cSDimitry Andric     return std::move(Err);
139349cc55cSDimitry Andric 
140349cc55cSDimitry Andric   // Add JIT-dispatch function support symbols.
14106c3fb27SDimitry Andric   if (auto Err = PlatformJD.define(
14206c3fb27SDimitry Andric           absoluteSymbols({{ES.intern("__orc_rt_jit_dispatch"),
14306c3fb27SDimitry Andric                             {EPC.getJITDispatchInfo().JITDispatchFunction,
144349cc55cSDimitry Andric                              JITSymbolFlags::Exported}},
145349cc55cSDimitry Andric                            {ES.intern("__orc_rt_jit_dispatch_ctx"),
14606c3fb27SDimitry Andric                             {EPC.getJITDispatchInfo().JITDispatchContext,
147349cc55cSDimitry Andric                              JITSymbolFlags::Exported}}})))
148349cc55cSDimitry Andric     return std::move(Err);
149349cc55cSDimitry Andric 
150349cc55cSDimitry Andric   // Create the instance.
151349cc55cSDimitry Andric   Error Err = Error::success();
15206c3fb27SDimitry Andric   auto P = std::unique_ptr<ELFNixPlatform>(new ELFNixPlatform(
15306c3fb27SDimitry Andric       ES, ObjLinkingLayer, PlatformJD, std::move(OrcRuntime), Err));
154349cc55cSDimitry Andric   if (Err)
155349cc55cSDimitry Andric     return std::move(Err);
156349cc55cSDimitry Andric   return std::move(P);
157349cc55cSDimitry Andric }
158349cc55cSDimitry Andric 
15906c3fb27SDimitry Andric Expected<std::unique_ptr<ELFNixPlatform>>
Create(ExecutionSession & ES,ObjectLinkingLayer & ObjLinkingLayer,JITDylib & PlatformJD,const char * OrcRuntimePath,std::optional<SymbolAliasMap> RuntimeAliases)16006c3fb27SDimitry Andric ELFNixPlatform::Create(ExecutionSession &ES,
16106c3fb27SDimitry Andric                        ObjectLinkingLayer &ObjLinkingLayer,
16206c3fb27SDimitry Andric                        JITDylib &PlatformJD, const char *OrcRuntimePath,
16306c3fb27SDimitry Andric                        std::optional<SymbolAliasMap> RuntimeAliases) {
16406c3fb27SDimitry Andric 
16506c3fb27SDimitry Andric   // Create a generator for the ORC runtime archive.
16606c3fb27SDimitry Andric   auto OrcRuntimeArchiveGenerator =
16706c3fb27SDimitry Andric       StaticLibraryDefinitionGenerator::Load(ObjLinkingLayer, OrcRuntimePath);
16806c3fb27SDimitry Andric   if (!OrcRuntimeArchiveGenerator)
16906c3fb27SDimitry Andric     return OrcRuntimeArchiveGenerator.takeError();
17006c3fb27SDimitry Andric 
17106c3fb27SDimitry Andric   return Create(ES, ObjLinkingLayer, PlatformJD,
17206c3fb27SDimitry Andric                 std::move(*OrcRuntimeArchiveGenerator),
17306c3fb27SDimitry Andric                 std::move(RuntimeAliases));
17406c3fb27SDimitry Andric }
17506c3fb27SDimitry Andric 
setupJITDylib(JITDylib & JD)176349cc55cSDimitry Andric Error ELFNixPlatform::setupJITDylib(JITDylib &JD) {
177349cc55cSDimitry Andric   return JD.define(
178349cc55cSDimitry Andric       std::make_unique<DSOHandleMaterializationUnit>(*this, DSOHandleSymbol));
179349cc55cSDimitry Andric }
180349cc55cSDimitry Andric 
teardownJITDylib(JITDylib & JD)18104eeddc0SDimitry Andric Error ELFNixPlatform::teardownJITDylib(JITDylib &JD) {
18204eeddc0SDimitry Andric   return Error::success();
18304eeddc0SDimitry Andric }
18404eeddc0SDimitry Andric 
notifyAdding(ResourceTracker & RT,const MaterializationUnit & MU)185349cc55cSDimitry Andric Error ELFNixPlatform::notifyAdding(ResourceTracker &RT,
186349cc55cSDimitry Andric                                    const MaterializationUnit &MU) {
187349cc55cSDimitry Andric   auto &JD = RT.getJITDylib();
188349cc55cSDimitry Andric   const auto &InitSym = MU.getInitializerSymbol();
189349cc55cSDimitry Andric   if (!InitSym)
190349cc55cSDimitry Andric     return Error::success();
191349cc55cSDimitry Andric 
192349cc55cSDimitry Andric   RegisteredInitSymbols[&JD].add(InitSym,
193349cc55cSDimitry Andric                                  SymbolLookupFlags::WeaklyReferencedSymbol);
194349cc55cSDimitry Andric   LLVM_DEBUG({
195349cc55cSDimitry Andric     dbgs() << "ELFNixPlatform: Registered init symbol " << *InitSym
196349cc55cSDimitry Andric            << " for MU " << MU.getName() << "\n";
197349cc55cSDimitry Andric   });
198349cc55cSDimitry Andric   return Error::success();
199349cc55cSDimitry Andric }
200349cc55cSDimitry Andric 
notifyRemoving(ResourceTracker & RT)201349cc55cSDimitry Andric Error ELFNixPlatform::notifyRemoving(ResourceTracker &RT) {
202349cc55cSDimitry Andric   llvm_unreachable("Not supported yet");
203349cc55cSDimitry Andric }
204349cc55cSDimitry Andric 
addAliases(ExecutionSession & ES,SymbolAliasMap & Aliases,ArrayRef<std::pair<const char *,const char * >> AL)205349cc55cSDimitry Andric static void addAliases(ExecutionSession &ES, SymbolAliasMap &Aliases,
206349cc55cSDimitry Andric                        ArrayRef<std::pair<const char *, const char *>> AL) {
207349cc55cSDimitry Andric   for (auto &KV : AL) {
208349cc55cSDimitry Andric     auto AliasName = ES.intern(KV.first);
209349cc55cSDimitry Andric     assert(!Aliases.count(AliasName) && "Duplicate symbol name in alias map");
210349cc55cSDimitry Andric     Aliases[std::move(AliasName)] = {ES.intern(KV.second),
211349cc55cSDimitry Andric                                      JITSymbolFlags::Exported};
212349cc55cSDimitry Andric   }
213349cc55cSDimitry Andric }
214349cc55cSDimitry Andric 
21581ad6265SDimitry Andric Expected<SymbolAliasMap>
standardPlatformAliases(ExecutionSession & ES,JITDylib & PlatformJD)21681ad6265SDimitry Andric ELFNixPlatform::standardPlatformAliases(ExecutionSession &ES,
21781ad6265SDimitry Andric                                         JITDylib &PlatformJD) {
218349cc55cSDimitry Andric   SymbolAliasMap Aliases;
219349cc55cSDimitry Andric   addAliases(ES, Aliases, requiredCXXAliases());
220349cc55cSDimitry Andric   addAliases(ES, Aliases, standardRuntimeUtilityAliases());
221349cc55cSDimitry Andric   return Aliases;
222349cc55cSDimitry Andric }
223349cc55cSDimitry Andric 
224349cc55cSDimitry Andric ArrayRef<std::pair<const char *, const char *>>
requiredCXXAliases()225349cc55cSDimitry Andric ELFNixPlatform::requiredCXXAliases() {
226349cc55cSDimitry Andric   static const std::pair<const char *, const char *> RequiredCXXAliases[] = {
227349cc55cSDimitry Andric       {"__cxa_atexit", "__orc_rt_elfnix_cxa_atexit"},
228349cc55cSDimitry Andric       {"atexit", "__orc_rt_elfnix_atexit"}};
229349cc55cSDimitry Andric 
230349cc55cSDimitry Andric   return ArrayRef<std::pair<const char *, const char *>>(RequiredCXXAliases);
231349cc55cSDimitry Andric }
232349cc55cSDimitry Andric 
233349cc55cSDimitry Andric ArrayRef<std::pair<const char *, const char *>>
standardRuntimeUtilityAliases()234349cc55cSDimitry Andric ELFNixPlatform::standardRuntimeUtilityAliases() {
235349cc55cSDimitry Andric   static const std::pair<const char *, const char *>
236349cc55cSDimitry Andric       StandardRuntimeUtilityAliases[] = {
237349cc55cSDimitry Andric           {"__orc_rt_run_program", "__orc_rt_elfnix_run_program"},
23881ad6265SDimitry Andric           {"__orc_rt_jit_dlerror", "__orc_rt_elfnix_jit_dlerror"},
23981ad6265SDimitry Andric           {"__orc_rt_jit_dlopen", "__orc_rt_elfnix_jit_dlopen"},
24081ad6265SDimitry Andric           {"__orc_rt_jit_dlclose", "__orc_rt_elfnix_jit_dlclose"},
24181ad6265SDimitry Andric           {"__orc_rt_jit_dlsym", "__orc_rt_elfnix_jit_dlsym"},
242349cc55cSDimitry Andric           {"__orc_rt_log_error", "__orc_rt_log_error_to_stderr"}};
243349cc55cSDimitry Andric 
244349cc55cSDimitry Andric   return ArrayRef<std::pair<const char *, const char *>>(
245349cc55cSDimitry Andric       StandardRuntimeUtilityAliases);
246349cc55cSDimitry Andric }
247349cc55cSDimitry Andric 
supportedTarget(const Triple & TT)248349cc55cSDimitry Andric bool ELFNixPlatform::supportedTarget(const Triple &TT) {
249349cc55cSDimitry Andric   switch (TT.getArch()) {
250349cc55cSDimitry Andric   case Triple::x86_64:
25181ad6265SDimitry Andric   case Triple::aarch64:
252*5f757f3fSDimitry Andric   // FIXME: jitlink for ppc64 hasn't been well tested, leave it unsupported
253*5f757f3fSDimitry Andric   // right now.
254*5f757f3fSDimitry Andric   case Triple::ppc64le:
255349cc55cSDimitry Andric     return true;
256349cc55cSDimitry Andric   default:
257349cc55cSDimitry Andric     return false;
258349cc55cSDimitry Andric   }
259349cc55cSDimitry Andric }
260349cc55cSDimitry Andric 
ELFNixPlatform(ExecutionSession & ES,ObjectLinkingLayer & ObjLinkingLayer,JITDylib & PlatformJD,std::unique_ptr<DefinitionGenerator> OrcRuntimeGenerator,Error & Err)261349cc55cSDimitry Andric ELFNixPlatform::ELFNixPlatform(
262349cc55cSDimitry Andric     ExecutionSession &ES, ObjectLinkingLayer &ObjLinkingLayer,
263349cc55cSDimitry Andric     JITDylib &PlatformJD,
264349cc55cSDimitry Andric     std::unique_ptr<DefinitionGenerator> OrcRuntimeGenerator, Error &Err)
265349cc55cSDimitry Andric     : ES(ES), ObjLinkingLayer(ObjLinkingLayer),
266349cc55cSDimitry Andric       DSOHandleSymbol(ES.intern("__dso_handle")) {
267349cc55cSDimitry Andric   ErrorAsOutParameter _(&Err);
268349cc55cSDimitry Andric 
269349cc55cSDimitry Andric   ObjLinkingLayer.addPlugin(std::make_unique<ELFNixPlatformPlugin>(*this));
270349cc55cSDimitry Andric 
271349cc55cSDimitry Andric   PlatformJD.addGenerator(std::move(OrcRuntimeGenerator));
272349cc55cSDimitry Andric 
273349cc55cSDimitry Andric   // PlatformJD hasn't been 'set-up' by the platform yet (since we're creating
274349cc55cSDimitry Andric   // the platform now), so set it up.
275349cc55cSDimitry Andric   if (auto E2 = setupJITDylib(PlatformJD)) {
276349cc55cSDimitry Andric     Err = std::move(E2);
277349cc55cSDimitry Andric     return;
278349cc55cSDimitry Andric   }
279349cc55cSDimitry Andric 
280349cc55cSDimitry Andric   RegisteredInitSymbols[&PlatformJD].add(
281349cc55cSDimitry Andric       DSOHandleSymbol, SymbolLookupFlags::WeaklyReferencedSymbol);
282349cc55cSDimitry Andric 
283349cc55cSDimitry Andric   // Associate wrapper function tags with JIT-side function implementations.
284349cc55cSDimitry Andric   if (auto E2 = associateRuntimeSupportFunctions(PlatformJD)) {
285349cc55cSDimitry Andric     Err = std::move(E2);
286349cc55cSDimitry Andric     return;
287349cc55cSDimitry Andric   }
288349cc55cSDimitry Andric 
289349cc55cSDimitry Andric   // Lookup addresses of runtime functions callable by the platform,
290349cc55cSDimitry Andric   // call the platform bootstrap function to initialize the platform-state
291349cc55cSDimitry Andric   // object in the executor.
292349cc55cSDimitry Andric   if (auto E2 = bootstrapELFNixRuntime(PlatformJD)) {
293349cc55cSDimitry Andric     Err = std::move(E2);
294349cc55cSDimitry Andric     return;
295349cc55cSDimitry Andric   }
296349cc55cSDimitry Andric }
297349cc55cSDimitry Andric 
associateRuntimeSupportFunctions(JITDylib & PlatformJD)298349cc55cSDimitry Andric Error ELFNixPlatform::associateRuntimeSupportFunctions(JITDylib &PlatformJD) {
299349cc55cSDimitry Andric   ExecutionSession::JITDispatchHandlerAssociationMap WFs;
300349cc55cSDimitry Andric 
301349cc55cSDimitry Andric   using GetInitializersSPSSig =
302349cc55cSDimitry Andric       SPSExpected<SPSELFNixJITDylibInitializerSequence>(SPSString);
303349cc55cSDimitry Andric   WFs[ES.intern("__orc_rt_elfnix_get_initializers_tag")] =
304349cc55cSDimitry Andric       ES.wrapAsyncWithSPS<GetInitializersSPSSig>(
305349cc55cSDimitry Andric           this, &ELFNixPlatform::rt_getInitializers);
306349cc55cSDimitry Andric 
307349cc55cSDimitry Andric   using GetDeinitializersSPSSig =
308349cc55cSDimitry Andric       SPSExpected<SPSELFJITDylibDeinitializerSequence>(SPSExecutorAddr);
309349cc55cSDimitry Andric   WFs[ES.intern("__orc_rt_elfnix_get_deinitializers_tag")] =
310349cc55cSDimitry Andric       ES.wrapAsyncWithSPS<GetDeinitializersSPSSig>(
311349cc55cSDimitry Andric           this, &ELFNixPlatform::rt_getDeinitializers);
312349cc55cSDimitry Andric 
313349cc55cSDimitry Andric   using LookupSymbolSPSSig =
314349cc55cSDimitry Andric       SPSExpected<SPSExecutorAddr>(SPSExecutorAddr, SPSString);
315349cc55cSDimitry Andric   WFs[ES.intern("__orc_rt_elfnix_symbol_lookup_tag")] =
316349cc55cSDimitry Andric       ES.wrapAsyncWithSPS<LookupSymbolSPSSig>(this,
317349cc55cSDimitry Andric                                               &ELFNixPlatform::rt_lookupSymbol);
318349cc55cSDimitry Andric 
319349cc55cSDimitry Andric   return ES.registerJITDispatchHandlers(PlatformJD, std::move(WFs));
320349cc55cSDimitry Andric }
321349cc55cSDimitry Andric 
getInitializersBuildSequencePhase(SendInitializerSequenceFn SendResult,JITDylib & JD,std::vector<JITDylibSP> DFSLinkOrder)322349cc55cSDimitry Andric void ELFNixPlatform::getInitializersBuildSequencePhase(
323349cc55cSDimitry Andric     SendInitializerSequenceFn SendResult, JITDylib &JD,
324349cc55cSDimitry Andric     std::vector<JITDylibSP> DFSLinkOrder) {
325349cc55cSDimitry Andric   ELFNixJITDylibInitializerSequence FullInitSeq;
326349cc55cSDimitry Andric   {
327349cc55cSDimitry Andric     std::lock_guard<std::mutex> Lock(PlatformMutex);
328349cc55cSDimitry Andric     for (auto &InitJD : reverse(DFSLinkOrder)) {
329349cc55cSDimitry Andric       LLVM_DEBUG({
330349cc55cSDimitry Andric         dbgs() << "ELFNixPlatform: Appending inits for \"" << InitJD->getName()
331349cc55cSDimitry Andric                << "\" to sequence\n";
332349cc55cSDimitry Andric       });
333349cc55cSDimitry Andric       auto ISItr = InitSeqs.find(InitJD.get());
334349cc55cSDimitry Andric       if (ISItr != InitSeqs.end()) {
335349cc55cSDimitry Andric         FullInitSeq.emplace_back(std::move(ISItr->second));
336349cc55cSDimitry Andric         InitSeqs.erase(ISItr);
337349cc55cSDimitry Andric       }
338349cc55cSDimitry Andric     }
339349cc55cSDimitry Andric   }
340349cc55cSDimitry Andric 
341349cc55cSDimitry Andric   SendResult(std::move(FullInitSeq));
342349cc55cSDimitry Andric }
343349cc55cSDimitry Andric 
getInitializersLookupPhase(SendInitializerSequenceFn SendResult,JITDylib & JD)344349cc55cSDimitry Andric void ELFNixPlatform::getInitializersLookupPhase(
345349cc55cSDimitry Andric     SendInitializerSequenceFn SendResult, JITDylib &JD) {
346349cc55cSDimitry Andric 
347349cc55cSDimitry Andric   auto DFSLinkOrder = JD.getDFSLinkOrder();
34804eeddc0SDimitry Andric   if (!DFSLinkOrder) {
34904eeddc0SDimitry Andric     SendResult(DFSLinkOrder.takeError());
35004eeddc0SDimitry Andric     return;
35104eeddc0SDimitry Andric   }
35204eeddc0SDimitry Andric 
353349cc55cSDimitry Andric   DenseMap<JITDylib *, SymbolLookupSet> NewInitSymbols;
354349cc55cSDimitry Andric   ES.runSessionLocked([&]() {
35504eeddc0SDimitry Andric     for (auto &InitJD : *DFSLinkOrder) {
356349cc55cSDimitry Andric       auto RISItr = RegisteredInitSymbols.find(InitJD.get());
357349cc55cSDimitry Andric       if (RISItr != RegisteredInitSymbols.end()) {
358349cc55cSDimitry Andric         NewInitSymbols[InitJD.get()] = std::move(RISItr->second);
359349cc55cSDimitry Andric         RegisteredInitSymbols.erase(RISItr);
360349cc55cSDimitry Andric       }
361349cc55cSDimitry Andric     }
362349cc55cSDimitry Andric   });
363349cc55cSDimitry Andric 
364349cc55cSDimitry Andric   // If there are no further init symbols to look up then move on to the next
365349cc55cSDimitry Andric   // phase.
366349cc55cSDimitry Andric   if (NewInitSymbols.empty()) {
367349cc55cSDimitry Andric     getInitializersBuildSequencePhase(std::move(SendResult), JD,
36804eeddc0SDimitry Andric                                       std::move(*DFSLinkOrder));
369349cc55cSDimitry Andric     return;
370349cc55cSDimitry Andric   }
371349cc55cSDimitry Andric 
372349cc55cSDimitry Andric   // Otherwise issue a lookup and re-run this phase when it completes.
373349cc55cSDimitry Andric   lookupInitSymbolsAsync(
374349cc55cSDimitry Andric       [this, SendResult = std::move(SendResult), &JD](Error Err) mutable {
375349cc55cSDimitry Andric         if (Err)
376349cc55cSDimitry Andric           SendResult(std::move(Err));
377349cc55cSDimitry Andric         else
378349cc55cSDimitry Andric           getInitializersLookupPhase(std::move(SendResult), JD);
379349cc55cSDimitry Andric       },
380349cc55cSDimitry Andric       ES, std::move(NewInitSymbols));
381349cc55cSDimitry Andric }
382349cc55cSDimitry Andric 
rt_getInitializers(SendInitializerSequenceFn SendResult,StringRef JDName)383349cc55cSDimitry Andric void ELFNixPlatform::rt_getInitializers(SendInitializerSequenceFn SendResult,
384349cc55cSDimitry Andric                                         StringRef JDName) {
385349cc55cSDimitry Andric   LLVM_DEBUG({
386349cc55cSDimitry Andric     dbgs() << "ELFNixPlatform::rt_getInitializers(\"" << JDName << "\")\n";
387349cc55cSDimitry Andric   });
388349cc55cSDimitry Andric 
389349cc55cSDimitry Andric   JITDylib *JD = ES.getJITDylibByName(JDName);
390349cc55cSDimitry Andric   if (!JD) {
391349cc55cSDimitry Andric     LLVM_DEBUG({
392349cc55cSDimitry Andric       dbgs() << "  No such JITDylib \"" << JDName << "\". Sending error.\n";
393349cc55cSDimitry Andric     });
394349cc55cSDimitry Andric     SendResult(make_error<StringError>("No JITDylib named " + JDName,
395349cc55cSDimitry Andric                                        inconvertibleErrorCode()));
396349cc55cSDimitry Andric     return;
397349cc55cSDimitry Andric   }
398349cc55cSDimitry Andric 
399349cc55cSDimitry Andric   getInitializersLookupPhase(std::move(SendResult), *JD);
400349cc55cSDimitry Andric }
401349cc55cSDimitry Andric 
rt_getDeinitializers(SendDeinitializerSequenceFn SendResult,ExecutorAddr Handle)402349cc55cSDimitry Andric void ELFNixPlatform::rt_getDeinitializers(
403349cc55cSDimitry Andric     SendDeinitializerSequenceFn SendResult, ExecutorAddr Handle) {
404349cc55cSDimitry Andric   LLVM_DEBUG({
40506c3fb27SDimitry Andric     dbgs() << "ELFNixPlatform::rt_getDeinitializers(\"" << Handle << "\")\n";
406349cc55cSDimitry Andric   });
407349cc55cSDimitry Andric 
408349cc55cSDimitry Andric   JITDylib *JD = nullptr;
409349cc55cSDimitry Andric 
410349cc55cSDimitry Andric   {
411349cc55cSDimitry Andric     std::lock_guard<std::mutex> Lock(PlatformMutex);
41204eeddc0SDimitry Andric     auto I = HandleAddrToJITDylib.find(Handle);
413349cc55cSDimitry Andric     if (I != HandleAddrToJITDylib.end())
414349cc55cSDimitry Andric       JD = I->second;
415349cc55cSDimitry Andric   }
416349cc55cSDimitry Andric 
417349cc55cSDimitry Andric   if (!JD) {
41806c3fb27SDimitry Andric     LLVM_DEBUG(dbgs() << "  No JITDylib for handle " << Handle << "\n");
419349cc55cSDimitry Andric     SendResult(make_error<StringError>("No JITDylib associated with handle " +
42006c3fb27SDimitry Andric                                            formatv("{0:x}", Handle),
421349cc55cSDimitry Andric                                        inconvertibleErrorCode()));
422349cc55cSDimitry Andric     return;
423349cc55cSDimitry Andric   }
424349cc55cSDimitry Andric 
425349cc55cSDimitry Andric   SendResult(ELFNixJITDylibDeinitializerSequence());
426349cc55cSDimitry Andric }
427349cc55cSDimitry Andric 
rt_lookupSymbol(SendSymbolAddressFn SendResult,ExecutorAddr Handle,StringRef SymbolName)428349cc55cSDimitry Andric void ELFNixPlatform::rt_lookupSymbol(SendSymbolAddressFn SendResult,
429349cc55cSDimitry Andric                                      ExecutorAddr Handle,
430349cc55cSDimitry Andric                                      StringRef SymbolName) {
431349cc55cSDimitry Andric   LLVM_DEBUG({
43206c3fb27SDimitry Andric     dbgs() << "ELFNixPlatform::rt_lookupSymbol(\"" << Handle << "\")\n";
433349cc55cSDimitry Andric   });
434349cc55cSDimitry Andric 
435349cc55cSDimitry Andric   JITDylib *JD = nullptr;
436349cc55cSDimitry Andric 
437349cc55cSDimitry Andric   {
438349cc55cSDimitry Andric     std::lock_guard<std::mutex> Lock(PlatformMutex);
43904eeddc0SDimitry Andric     auto I = HandleAddrToJITDylib.find(Handle);
440349cc55cSDimitry Andric     if (I != HandleAddrToJITDylib.end())
441349cc55cSDimitry Andric       JD = I->second;
442349cc55cSDimitry Andric   }
443349cc55cSDimitry Andric 
444349cc55cSDimitry Andric   if (!JD) {
44506c3fb27SDimitry Andric     LLVM_DEBUG(dbgs() << "  No JITDylib for handle " << Handle << "\n");
446349cc55cSDimitry Andric     SendResult(make_error<StringError>("No JITDylib associated with handle " +
44706c3fb27SDimitry Andric                                            formatv("{0:x}", Handle),
448349cc55cSDimitry Andric                                        inconvertibleErrorCode()));
449349cc55cSDimitry Andric     return;
450349cc55cSDimitry Andric   }
451349cc55cSDimitry Andric 
452349cc55cSDimitry Andric   // Use functor class to work around XL build compiler issue on AIX.
453349cc55cSDimitry Andric   class RtLookupNotifyComplete {
454349cc55cSDimitry Andric   public:
455349cc55cSDimitry Andric     RtLookupNotifyComplete(SendSymbolAddressFn &&SendResult)
456349cc55cSDimitry Andric         : SendResult(std::move(SendResult)) {}
457349cc55cSDimitry Andric     void operator()(Expected<SymbolMap> Result) {
458349cc55cSDimitry Andric       if (Result) {
459349cc55cSDimitry Andric         assert(Result->size() == 1 && "Unexpected result map count");
46006c3fb27SDimitry Andric         SendResult(Result->begin()->second.getAddress());
461349cc55cSDimitry Andric       } else {
462349cc55cSDimitry Andric         SendResult(Result.takeError());
463349cc55cSDimitry Andric       }
464349cc55cSDimitry Andric     }
465349cc55cSDimitry Andric 
466349cc55cSDimitry Andric   private:
467349cc55cSDimitry Andric     SendSymbolAddressFn SendResult;
468349cc55cSDimitry Andric   };
469349cc55cSDimitry Andric 
470349cc55cSDimitry Andric   ES.lookup(
471349cc55cSDimitry Andric       LookupKind::DLSym, {{JD, JITDylibLookupFlags::MatchExportedSymbolsOnly}},
472349cc55cSDimitry Andric       SymbolLookupSet(ES.intern(SymbolName)), SymbolState::Ready,
473349cc55cSDimitry Andric       RtLookupNotifyComplete(std::move(SendResult)), NoDependenciesToRegister);
474349cc55cSDimitry Andric }
475349cc55cSDimitry Andric 
bootstrapELFNixRuntime(JITDylib & PlatformJD)476349cc55cSDimitry Andric Error ELFNixPlatform::bootstrapELFNixRuntime(JITDylib &PlatformJD) {
477349cc55cSDimitry Andric 
478349cc55cSDimitry Andric   std::pair<const char *, ExecutorAddr *> Symbols[] = {
479349cc55cSDimitry Andric       {"__orc_rt_elfnix_platform_bootstrap", &orc_rt_elfnix_platform_bootstrap},
480349cc55cSDimitry Andric       {"__orc_rt_elfnix_platform_shutdown", &orc_rt_elfnix_platform_shutdown},
481349cc55cSDimitry Andric       {"__orc_rt_elfnix_register_object_sections",
482349cc55cSDimitry Andric        &orc_rt_elfnix_register_object_sections},
483349cc55cSDimitry Andric       {"__orc_rt_elfnix_create_pthread_key",
484349cc55cSDimitry Andric        &orc_rt_elfnix_create_pthread_key}};
485349cc55cSDimitry Andric 
486349cc55cSDimitry Andric   SymbolLookupSet RuntimeSymbols;
487349cc55cSDimitry Andric   std::vector<std::pair<SymbolStringPtr, ExecutorAddr *>> AddrsToRecord;
488349cc55cSDimitry Andric   for (const auto &KV : Symbols) {
489349cc55cSDimitry Andric     auto Name = ES.intern(KV.first);
490349cc55cSDimitry Andric     RuntimeSymbols.add(Name);
491349cc55cSDimitry Andric     AddrsToRecord.push_back({std::move(Name), KV.second});
492349cc55cSDimitry Andric   }
493349cc55cSDimitry Andric 
494349cc55cSDimitry Andric   auto RuntimeSymbolAddrs = ES.lookup(
495349cc55cSDimitry Andric       {{&PlatformJD, JITDylibLookupFlags::MatchAllSymbols}}, RuntimeSymbols);
496349cc55cSDimitry Andric   if (!RuntimeSymbolAddrs)
497349cc55cSDimitry Andric     return RuntimeSymbolAddrs.takeError();
498349cc55cSDimitry Andric 
499349cc55cSDimitry Andric   for (const auto &KV : AddrsToRecord) {
500349cc55cSDimitry Andric     auto &Name = KV.first;
501349cc55cSDimitry Andric     assert(RuntimeSymbolAddrs->count(Name) && "Missing runtime symbol?");
50206c3fb27SDimitry Andric     *KV.second = (*RuntimeSymbolAddrs)[Name].getAddress();
503349cc55cSDimitry Andric   }
504349cc55cSDimitry Andric 
505349cc55cSDimitry Andric   auto PJDDSOHandle = ES.lookup(
506349cc55cSDimitry Andric       {{&PlatformJD, JITDylibLookupFlags::MatchAllSymbols}}, DSOHandleSymbol);
507349cc55cSDimitry Andric   if (!PJDDSOHandle)
508349cc55cSDimitry Andric     return PJDDSOHandle.takeError();
509349cc55cSDimitry Andric 
510349cc55cSDimitry Andric   if (auto Err = ES.callSPSWrapper<void(uint64_t)>(
51106c3fb27SDimitry Andric           orc_rt_elfnix_platform_bootstrap,
51206c3fb27SDimitry Andric           PJDDSOHandle->getAddress().getValue()))
513349cc55cSDimitry Andric     return Err;
514349cc55cSDimitry Andric 
515349cc55cSDimitry Andric   // FIXME: Ordering is fuzzy here. We're probably best off saying
516349cc55cSDimitry Andric   // "behavior is undefined if code that uses the runtime is added before
517349cc55cSDimitry Andric   // the platform constructor returns", then move all this to the constructor.
518349cc55cSDimitry Andric   RuntimeBootstrapped = true;
519349cc55cSDimitry Andric   std::vector<ELFPerObjectSectionsToRegister> DeferredPOSRs;
520349cc55cSDimitry Andric   {
521349cc55cSDimitry Andric     std::lock_guard<std::mutex> Lock(PlatformMutex);
522349cc55cSDimitry Andric     DeferredPOSRs = std::move(BootstrapPOSRs);
523349cc55cSDimitry Andric   }
524349cc55cSDimitry Andric 
525349cc55cSDimitry Andric   for (auto &D : DeferredPOSRs)
526349cc55cSDimitry Andric     if (auto Err = registerPerObjectSections(D))
527349cc55cSDimitry Andric       return Err;
528349cc55cSDimitry Andric 
529349cc55cSDimitry Andric   return Error::success();
530349cc55cSDimitry Andric }
531349cc55cSDimitry Andric 
registerInitInfo(JITDylib & JD,ArrayRef<jitlink::Section * > InitSections)532349cc55cSDimitry Andric Error ELFNixPlatform::registerInitInfo(
533349cc55cSDimitry Andric     JITDylib &JD, ArrayRef<jitlink::Section *> InitSections) {
534349cc55cSDimitry Andric 
535349cc55cSDimitry Andric   std::unique_lock<std::mutex> Lock(PlatformMutex);
536349cc55cSDimitry Andric 
537349cc55cSDimitry Andric   ELFNixJITDylibInitializers *InitSeq = nullptr;
538349cc55cSDimitry Andric   {
539349cc55cSDimitry Andric     auto I = InitSeqs.find(&JD);
540349cc55cSDimitry Andric     if (I == InitSeqs.end()) {
541349cc55cSDimitry Andric       // If there's no init sequence entry yet then we need to look up the
542349cc55cSDimitry Andric       // header symbol to force creation of one.
543349cc55cSDimitry Andric       Lock.unlock();
544349cc55cSDimitry Andric 
545349cc55cSDimitry Andric       auto SearchOrder =
546349cc55cSDimitry Andric           JD.withLinkOrderDo([](const JITDylibSearchOrder &SO) { return SO; });
547349cc55cSDimitry Andric       if (auto Err = ES.lookup(SearchOrder, DSOHandleSymbol).takeError())
548349cc55cSDimitry Andric         return Err;
549349cc55cSDimitry Andric 
550349cc55cSDimitry Andric       Lock.lock();
551349cc55cSDimitry Andric       I = InitSeqs.find(&JD);
552349cc55cSDimitry Andric       assert(I != InitSeqs.end() &&
553349cc55cSDimitry Andric              "Entry missing after header symbol lookup?");
554349cc55cSDimitry Andric     }
555349cc55cSDimitry Andric     InitSeq = &I->second;
556349cc55cSDimitry Andric   }
557349cc55cSDimitry Andric 
558349cc55cSDimitry Andric   for (auto *Sec : InitSections) {
559349cc55cSDimitry Andric     // FIXME: Avoid copy here.
560349cc55cSDimitry Andric     jitlink::SectionRange R(*Sec);
56106c3fb27SDimitry Andric     InitSeq->InitSections[Sec->getName()].push_back(R.getRange());
562349cc55cSDimitry Andric   }
563349cc55cSDimitry Andric 
564349cc55cSDimitry Andric   return Error::success();
565349cc55cSDimitry Andric }
566349cc55cSDimitry Andric 
registerPerObjectSections(const ELFPerObjectSectionsToRegister & POSR)567349cc55cSDimitry Andric Error ELFNixPlatform::registerPerObjectSections(
568349cc55cSDimitry Andric     const ELFPerObjectSectionsToRegister &POSR) {
569349cc55cSDimitry Andric 
570349cc55cSDimitry Andric   if (!orc_rt_elfnix_register_object_sections)
571349cc55cSDimitry Andric     return make_error<StringError>("Attempting to register per-object "
572349cc55cSDimitry Andric                                    "sections, but runtime support has not "
573349cc55cSDimitry Andric                                    "been loaded yet",
574349cc55cSDimitry Andric                                    inconvertibleErrorCode());
575349cc55cSDimitry Andric 
576349cc55cSDimitry Andric   Error ErrResult = Error::success();
577349cc55cSDimitry Andric   if (auto Err = ES.callSPSWrapper<shared::SPSError(
578349cc55cSDimitry Andric                      SPSELFPerObjectSectionsToRegister)>(
579349cc55cSDimitry Andric           orc_rt_elfnix_register_object_sections, ErrResult, POSR))
580349cc55cSDimitry Andric     return Err;
581349cc55cSDimitry Andric   return ErrResult;
582349cc55cSDimitry Andric }
583349cc55cSDimitry Andric 
createPThreadKey()584349cc55cSDimitry Andric Expected<uint64_t> ELFNixPlatform::createPThreadKey() {
585349cc55cSDimitry Andric   if (!orc_rt_elfnix_create_pthread_key)
586349cc55cSDimitry Andric     return make_error<StringError>(
587349cc55cSDimitry Andric         "Attempting to create pthread key in target, but runtime support has "
588349cc55cSDimitry Andric         "not been loaded yet",
589349cc55cSDimitry Andric         inconvertibleErrorCode());
590349cc55cSDimitry Andric 
591349cc55cSDimitry Andric   Expected<uint64_t> Result(0);
592349cc55cSDimitry Andric   if (auto Err = ES.callSPSWrapper<SPSExpected<uint64_t>(void)>(
593349cc55cSDimitry Andric           orc_rt_elfnix_create_pthread_key, Result))
594349cc55cSDimitry Andric     return std::move(Err);
595349cc55cSDimitry Andric   return Result;
596349cc55cSDimitry Andric }
597349cc55cSDimitry Andric 
modifyPassConfig(MaterializationResponsibility & MR,jitlink::LinkGraph & LG,jitlink::PassConfiguration & Config)598349cc55cSDimitry Andric void ELFNixPlatform::ELFNixPlatformPlugin::modifyPassConfig(
599349cc55cSDimitry Andric     MaterializationResponsibility &MR, jitlink::LinkGraph &LG,
600349cc55cSDimitry Andric     jitlink::PassConfiguration &Config) {
601349cc55cSDimitry Andric 
602349cc55cSDimitry Andric   // If the initializer symbol is the __dso_handle symbol then just add
603349cc55cSDimitry Andric   // the DSO handle support passes.
604349cc55cSDimitry Andric   if (MR.getInitializerSymbol() == MP.DSOHandleSymbol) {
605349cc55cSDimitry Andric     addDSOHandleSupportPasses(MR, Config);
606349cc55cSDimitry Andric     // The DSOHandle materialization unit doesn't require any other
607349cc55cSDimitry Andric     // support, so we can bail out early.
608349cc55cSDimitry Andric     return;
609349cc55cSDimitry Andric   }
610349cc55cSDimitry Andric 
611349cc55cSDimitry Andric   // If the object contains initializers then add passes to record them.
612349cc55cSDimitry Andric   if (MR.getInitializerSymbol())
613349cc55cSDimitry Andric     addInitializerSupportPasses(MR, Config);
614349cc55cSDimitry Andric 
615349cc55cSDimitry Andric   // Add passes for eh-frame and TLV support.
616349cc55cSDimitry Andric   addEHAndTLVSupportPasses(MR, Config);
617349cc55cSDimitry Andric }
618349cc55cSDimitry Andric 
619349cc55cSDimitry Andric ObjectLinkingLayer::Plugin::SyntheticSymbolDependenciesMap
getSyntheticSymbolDependencies(MaterializationResponsibility & MR)620349cc55cSDimitry Andric ELFNixPlatform::ELFNixPlatformPlugin::getSyntheticSymbolDependencies(
621349cc55cSDimitry Andric     MaterializationResponsibility &MR) {
622349cc55cSDimitry Andric   std::lock_guard<std::mutex> Lock(PluginMutex);
623349cc55cSDimitry Andric   auto I = InitSymbolDeps.find(&MR);
624349cc55cSDimitry Andric   if (I != InitSymbolDeps.end()) {
625349cc55cSDimitry Andric     SyntheticSymbolDependenciesMap Result;
626349cc55cSDimitry Andric     Result[MR.getInitializerSymbol()] = std::move(I->second);
627349cc55cSDimitry Andric     InitSymbolDeps.erase(&MR);
628349cc55cSDimitry Andric     return Result;
629349cc55cSDimitry Andric   }
630349cc55cSDimitry Andric   return SyntheticSymbolDependenciesMap();
631349cc55cSDimitry Andric }
632349cc55cSDimitry Andric 
addInitializerSupportPasses(MaterializationResponsibility & MR,jitlink::PassConfiguration & Config)633349cc55cSDimitry Andric void ELFNixPlatform::ELFNixPlatformPlugin::addInitializerSupportPasses(
634349cc55cSDimitry Andric     MaterializationResponsibility &MR, jitlink::PassConfiguration &Config) {
635349cc55cSDimitry Andric 
636349cc55cSDimitry Andric   /// Preserve init sections.
637349cc55cSDimitry Andric   Config.PrePrunePasses.push_back([this, &MR](jitlink::LinkGraph &G) -> Error {
638349cc55cSDimitry Andric     if (auto Err = preserveInitSections(G, MR))
639349cc55cSDimitry Andric       return Err;
640349cc55cSDimitry Andric     return Error::success();
641349cc55cSDimitry Andric   });
642349cc55cSDimitry Andric 
643349cc55cSDimitry Andric   Config.PostFixupPasses.push_back(
644349cc55cSDimitry Andric       [this, &JD = MR.getTargetJITDylib()](jitlink::LinkGraph &G) {
645349cc55cSDimitry Andric         return registerInitSections(G, JD);
646349cc55cSDimitry Andric       });
647349cc55cSDimitry Andric }
648349cc55cSDimitry Andric 
addDSOHandleSupportPasses(MaterializationResponsibility & MR,jitlink::PassConfiguration & Config)649349cc55cSDimitry Andric void ELFNixPlatform::ELFNixPlatformPlugin::addDSOHandleSupportPasses(
650349cc55cSDimitry Andric     MaterializationResponsibility &MR, jitlink::PassConfiguration &Config) {
651349cc55cSDimitry Andric 
652349cc55cSDimitry Andric   Config.PostAllocationPasses.push_back([this, &JD = MR.getTargetJITDylib()](
653349cc55cSDimitry Andric                                             jitlink::LinkGraph &G) -> Error {
654349cc55cSDimitry Andric     auto I = llvm::find_if(G.defined_symbols(), [this](jitlink::Symbol *Sym) {
655349cc55cSDimitry Andric       return Sym->getName() == *MP.DSOHandleSymbol;
656349cc55cSDimitry Andric     });
657349cc55cSDimitry Andric     assert(I != G.defined_symbols().end() && "Missing DSO handle symbol");
658349cc55cSDimitry Andric     {
659349cc55cSDimitry Andric       std::lock_guard<std::mutex> Lock(MP.PlatformMutex);
66004eeddc0SDimitry Andric       auto HandleAddr = (*I)->getAddress();
661349cc55cSDimitry Andric       MP.HandleAddrToJITDylib[HandleAddr] = &JD;
662349cc55cSDimitry Andric       assert(!MP.InitSeqs.count(&JD) && "InitSeq entry for JD already exists");
663349cc55cSDimitry Andric       MP.InitSeqs.insert(std::make_pair(
66404eeddc0SDimitry Andric           &JD, ELFNixJITDylibInitializers(JD.getName(), HandleAddr)));
665349cc55cSDimitry Andric     }
666349cc55cSDimitry Andric     return Error::success();
667349cc55cSDimitry Andric   });
668349cc55cSDimitry Andric }
669349cc55cSDimitry Andric 
addEHAndTLVSupportPasses(MaterializationResponsibility & MR,jitlink::PassConfiguration & Config)670349cc55cSDimitry Andric void ELFNixPlatform::ELFNixPlatformPlugin::addEHAndTLVSupportPasses(
671349cc55cSDimitry Andric     MaterializationResponsibility &MR, jitlink::PassConfiguration &Config) {
672349cc55cSDimitry Andric 
673349cc55cSDimitry Andric   // Insert TLV lowering at the start of the PostPrunePasses, since we want
674349cc55cSDimitry Andric   // it to run before GOT/PLT lowering.
675349cc55cSDimitry Andric 
676349cc55cSDimitry Andric   // TODO: Check that before the fixTLVSectionsAndEdges pass, the GOT/PLT build
677349cc55cSDimitry Andric   // pass has done. Because the TLS descriptor need to be allocate in GOT.
678349cc55cSDimitry Andric   Config.PostPrunePasses.push_back(
679349cc55cSDimitry Andric       [this, &JD = MR.getTargetJITDylib()](jitlink::LinkGraph &G) {
680349cc55cSDimitry Andric         return fixTLVSectionsAndEdges(G, JD);
681349cc55cSDimitry Andric       });
682349cc55cSDimitry Andric 
683349cc55cSDimitry Andric   // Add a pass to register the final addresses of the eh-frame and TLV sections
684349cc55cSDimitry Andric   // with the runtime.
685349cc55cSDimitry Andric   Config.PostFixupPasses.push_back([this](jitlink::LinkGraph &G) -> Error {
686349cc55cSDimitry Andric     ELFPerObjectSectionsToRegister POSR;
687349cc55cSDimitry Andric 
68806c3fb27SDimitry Andric     if (auto *EHFrameSection = G.findSectionByName(ELFEHFrameSectionName)) {
689349cc55cSDimitry Andric       jitlink::SectionRange R(*EHFrameSection);
690349cc55cSDimitry Andric       if (!R.empty())
69106c3fb27SDimitry Andric         POSR.EHFrameSection = R.getRange();
692349cc55cSDimitry Andric     }
693349cc55cSDimitry Andric 
694349cc55cSDimitry Andric     // Get a pointer to the thread data section if there is one. It will be used
695349cc55cSDimitry Andric     // below.
696349cc55cSDimitry Andric     jitlink::Section *ThreadDataSection =
69706c3fb27SDimitry Andric         G.findSectionByName(ELFThreadDataSectionName);
698349cc55cSDimitry Andric 
699349cc55cSDimitry Andric     // Handle thread BSS section if there is one.
70006c3fb27SDimitry Andric     if (auto *ThreadBSSSection = G.findSectionByName(ELFThreadBSSSectionName)) {
701349cc55cSDimitry Andric       // If there's already a thread data section in this graph then merge the
702349cc55cSDimitry Andric       // thread BSS section content into it, otherwise just treat the thread
703349cc55cSDimitry Andric       // BSS section as the thread data section.
704349cc55cSDimitry Andric       if (ThreadDataSection)
705349cc55cSDimitry Andric         G.mergeSections(*ThreadDataSection, *ThreadBSSSection);
706349cc55cSDimitry Andric       else
707349cc55cSDimitry Andric         ThreadDataSection = ThreadBSSSection;
708349cc55cSDimitry Andric     }
709349cc55cSDimitry Andric 
710349cc55cSDimitry Andric     // Having merged thread BSS (if present) and thread data (if present),
711349cc55cSDimitry Andric     // record the resulting section range.
712349cc55cSDimitry Andric     if (ThreadDataSection) {
713349cc55cSDimitry Andric       jitlink::SectionRange R(*ThreadDataSection);
714349cc55cSDimitry Andric       if (!R.empty())
71506c3fb27SDimitry Andric         POSR.ThreadDataSection = R.getRange();
716349cc55cSDimitry Andric     }
717349cc55cSDimitry Andric 
718349cc55cSDimitry Andric     if (POSR.EHFrameSection.Start || POSR.ThreadDataSection.Start) {
719349cc55cSDimitry Andric 
720349cc55cSDimitry Andric       // If we're still bootstrapping the runtime then just record this
721349cc55cSDimitry Andric       // frame for now.
722349cc55cSDimitry Andric       if (!MP.RuntimeBootstrapped) {
723349cc55cSDimitry Andric         std::lock_guard<std::mutex> Lock(MP.PlatformMutex);
724349cc55cSDimitry Andric         MP.BootstrapPOSRs.push_back(POSR);
725349cc55cSDimitry Andric         return Error::success();
726349cc55cSDimitry Andric       }
727349cc55cSDimitry Andric 
728349cc55cSDimitry Andric       // Otherwise register it immediately.
729349cc55cSDimitry Andric       if (auto Err = MP.registerPerObjectSections(POSR))
730349cc55cSDimitry Andric         return Err;
731349cc55cSDimitry Andric     }
732349cc55cSDimitry Andric 
733349cc55cSDimitry Andric     return Error::success();
734349cc55cSDimitry Andric   });
735349cc55cSDimitry Andric }
736349cc55cSDimitry Andric 
preserveInitSections(jitlink::LinkGraph & G,MaterializationResponsibility & MR)737349cc55cSDimitry Andric Error ELFNixPlatform::ELFNixPlatformPlugin::preserveInitSections(
738349cc55cSDimitry Andric     jitlink::LinkGraph &G, MaterializationResponsibility &MR) {
739349cc55cSDimitry Andric 
740349cc55cSDimitry Andric   JITLinkSymbolSet InitSectionSymbols;
74181ad6265SDimitry Andric   for (auto &InitSection : G.sections()) {
742349cc55cSDimitry Andric     // Skip non-init sections.
74306c3fb27SDimitry Andric     if (!isELFInitializerSection(InitSection.getName()))
744349cc55cSDimitry Andric       continue;
745349cc55cSDimitry Andric 
746349cc55cSDimitry Andric     // Make a pass over live symbols in the section: those blocks are already
747349cc55cSDimitry Andric     // preserved.
748349cc55cSDimitry Andric     DenseSet<jitlink::Block *> AlreadyLiveBlocks;
74981ad6265SDimitry Andric     for (auto &Sym : InitSection.symbols()) {
750349cc55cSDimitry Andric       auto &B = Sym->getBlock();
751349cc55cSDimitry Andric       if (Sym->isLive() && Sym->getOffset() == 0 &&
752349cc55cSDimitry Andric           Sym->getSize() == B.getSize() && !AlreadyLiveBlocks.count(&B)) {
753349cc55cSDimitry Andric         InitSectionSymbols.insert(Sym);
754349cc55cSDimitry Andric         AlreadyLiveBlocks.insert(&B);
755349cc55cSDimitry Andric       }
756349cc55cSDimitry Andric     }
757349cc55cSDimitry Andric 
758349cc55cSDimitry Andric     // Add anonymous symbols to preserve any not-already-preserved blocks.
75981ad6265SDimitry Andric     for (auto *B : InitSection.blocks())
760349cc55cSDimitry Andric       if (!AlreadyLiveBlocks.count(B))
761349cc55cSDimitry Andric         InitSectionSymbols.insert(
762349cc55cSDimitry Andric             &G.addAnonymousSymbol(*B, 0, B->getSize(), false, true));
763349cc55cSDimitry Andric   }
764349cc55cSDimitry Andric 
765349cc55cSDimitry Andric   if (!InitSectionSymbols.empty()) {
766349cc55cSDimitry Andric     std::lock_guard<std::mutex> Lock(PluginMutex);
767349cc55cSDimitry Andric     InitSymbolDeps[&MR] = std::move(InitSectionSymbols);
768349cc55cSDimitry Andric   }
769349cc55cSDimitry Andric 
770349cc55cSDimitry Andric   return Error::success();
771349cc55cSDimitry Andric }
772349cc55cSDimitry Andric 
registerInitSections(jitlink::LinkGraph & G,JITDylib & JD)773349cc55cSDimitry Andric Error ELFNixPlatform::ELFNixPlatformPlugin::registerInitSections(
774349cc55cSDimitry Andric     jitlink::LinkGraph &G, JITDylib &JD) {
775349cc55cSDimitry Andric 
776349cc55cSDimitry Andric   SmallVector<jitlink::Section *> InitSections;
777349cc55cSDimitry Andric 
77806c3fb27SDimitry Andric   LLVM_DEBUG(dbgs() << "ELFNixPlatform::registerInitSections\n");
779349cc55cSDimitry Andric 
78081ad6265SDimitry Andric   for (auto &Sec : G.sections()) {
78106c3fb27SDimitry Andric     if (isELFInitializerSection(Sec.getName())) {
78281ad6265SDimitry Andric       InitSections.push_back(&Sec);
783349cc55cSDimitry Andric     }
784349cc55cSDimitry Andric   }
785349cc55cSDimitry Andric 
786349cc55cSDimitry Andric   // Dump the scraped inits.
787349cc55cSDimitry Andric   LLVM_DEBUG({
788349cc55cSDimitry Andric     dbgs() << "ELFNixPlatform: Scraped " << G.getName() << " init sections:\n";
789349cc55cSDimitry Andric     for (auto *Sec : InitSections) {
790349cc55cSDimitry Andric       jitlink::SectionRange R(*Sec);
79106c3fb27SDimitry Andric       dbgs() << "  " << Sec->getName() << ": " << R.getRange() << "\n";
792349cc55cSDimitry Andric     }
793349cc55cSDimitry Andric   });
794349cc55cSDimitry Andric 
795349cc55cSDimitry Andric   return MP.registerInitInfo(JD, InitSections);
796349cc55cSDimitry Andric }
797349cc55cSDimitry Andric 
fixTLVSectionsAndEdges(jitlink::LinkGraph & G,JITDylib & JD)798349cc55cSDimitry Andric Error ELFNixPlatform::ELFNixPlatformPlugin::fixTLVSectionsAndEdges(
799349cc55cSDimitry Andric     jitlink::LinkGraph &G, JITDylib &JD) {
800349cc55cSDimitry Andric 
801753f127fSDimitry Andric   for (auto *Sym : G.external_symbols()) {
802349cc55cSDimitry Andric     if (Sym->getName() == "__tls_get_addr") {
803349cc55cSDimitry Andric       Sym->setName("___orc_rt_elfnix_tls_get_addr");
804753f127fSDimitry Andric     } else if (Sym->getName() == "__tlsdesc_resolver") {
805753f127fSDimitry Andric       Sym->setName("___orc_rt_elfnix_tlsdesc_resolver");
806753f127fSDimitry Andric     }
807349cc55cSDimitry Andric   }
808349cc55cSDimitry Andric 
809349cc55cSDimitry Andric   auto *TLSInfoEntrySection = G.findSectionByName("$__TLSINFO");
810349cc55cSDimitry Andric 
811349cc55cSDimitry Andric   if (TLSInfoEntrySection) {
812bdd1243dSDimitry Andric     std::optional<uint64_t> Key;
813349cc55cSDimitry Andric     {
814349cc55cSDimitry Andric       std::lock_guard<std::mutex> Lock(MP.PlatformMutex);
815349cc55cSDimitry Andric       auto I = MP.JITDylibToPThreadKey.find(&JD);
816349cc55cSDimitry Andric       if (I != MP.JITDylibToPThreadKey.end())
817349cc55cSDimitry Andric         Key = I->second;
818349cc55cSDimitry Andric     }
819349cc55cSDimitry Andric     if (!Key) {
820349cc55cSDimitry Andric       if (auto KeyOrErr = MP.createPThreadKey())
821349cc55cSDimitry Andric         Key = *KeyOrErr;
822349cc55cSDimitry Andric       else
823349cc55cSDimitry Andric         return KeyOrErr.takeError();
824349cc55cSDimitry Andric     }
825349cc55cSDimitry Andric 
826349cc55cSDimitry Andric     uint64_t PlatformKeyBits =
827349cc55cSDimitry Andric         support::endian::byte_swap(*Key, G.getEndianness());
828349cc55cSDimitry Andric 
829349cc55cSDimitry Andric     for (auto *B : TLSInfoEntrySection->blocks()) {
830349cc55cSDimitry Andric       // FIXME: The TLS descriptor byte length may different with different
831349cc55cSDimitry Andric       // ISA
832349cc55cSDimitry Andric       assert(B->getSize() == (G.getPointerSize() * 2) &&
833349cc55cSDimitry Andric              "TLS descriptor must be 2 words length");
834349cc55cSDimitry Andric       auto TLSInfoEntryContent = B->getMutableContent(G);
835349cc55cSDimitry Andric       memcpy(TLSInfoEntryContent.data(), &PlatformKeyBits, G.getPointerSize());
836349cc55cSDimitry Andric     }
837349cc55cSDimitry Andric   }
838349cc55cSDimitry Andric 
839349cc55cSDimitry Andric   return Error::success();
840349cc55cSDimitry Andric }
841349cc55cSDimitry Andric 
842349cc55cSDimitry Andric } // End namespace orc.
843349cc55cSDimitry Andric } // End namespace llvm.
844