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