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: 33349cc55cSDimitry Andric DSOHandleMaterializationUnit(ELFNixPlatform &ENP, 34349cc55cSDimitry Andric const SymbolStringPtr &DSOHandleSymbol) 350eae32dcSDimitry Andric : MaterializationUnit( 360eae32dcSDimitry Andric createDSOHandleSectionInterface(ENP, DSOHandleSymbol)), 37349cc55cSDimitry Andric ENP(ENP) {} 38349cc55cSDimitry Andric 39349cc55cSDimitry Andric StringRef getName() const override { return "DSOHandleMU"; } 40349cc55cSDimitry Andric 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 89349cc55cSDimitry Andric void discard(const JITDylib &JD, const SymbolStringPtr &Sym) override {} 90349cc55cSDimitry Andric 91349cc55cSDimitry Andric private: 920eae32dcSDimitry Andric static MaterializationUnit::Interface 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 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 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>> 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 176349cc55cSDimitry Andric Error ELFNixPlatform::setupJITDylib(JITDylib &JD) { 177349cc55cSDimitry Andric return JD.define( 178349cc55cSDimitry Andric std::make_unique<DSOHandleMaterializationUnit>(*this, DSOHandleSymbol)); 179349cc55cSDimitry Andric } 180349cc55cSDimitry Andric 18104eeddc0SDimitry Andric Error ELFNixPlatform::teardownJITDylib(JITDylib &JD) { 18204eeddc0SDimitry Andric return Error::success(); 18304eeddc0SDimitry Andric } 18404eeddc0SDimitry Andric 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 201349cc55cSDimitry Andric Error ELFNixPlatform::notifyRemoving(ResourceTracker &RT) { 202349cc55cSDimitry Andric llvm_unreachable("Not supported yet"); 203349cc55cSDimitry Andric } 204349cc55cSDimitry Andric 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> 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 *>> 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 *>> 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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