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