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