1*349cc55cSDimitry Andric //===------ ELFNixPlatform.cpp - Utilities for executing MachO in Orc -----===// 2*349cc55cSDimitry Andric // 3*349cc55cSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*349cc55cSDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5*349cc55cSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*349cc55cSDimitry Andric // 7*349cc55cSDimitry Andric //===----------------------------------------------------------------------===// 8*349cc55cSDimitry Andric 9*349cc55cSDimitry Andric #include "llvm/ExecutionEngine/Orc/ELFNixPlatform.h" 10*349cc55cSDimitry Andric 11*349cc55cSDimitry Andric #include "llvm/BinaryFormat/ELF.h" 12*349cc55cSDimitry Andric #include "llvm/ExecutionEngine/JITLink/ELF_x86_64.h" 13*349cc55cSDimitry Andric #include "llvm/ExecutionEngine/JITLink/x86_64.h" 14*349cc55cSDimitry Andric #include "llvm/ExecutionEngine/Orc/DebugUtils.h" 15*349cc55cSDimitry Andric #include "llvm/ExecutionEngine/Orc/ExecutionUtils.h" 16*349cc55cSDimitry Andric #include "llvm/Support/BinaryByteStream.h" 17*349cc55cSDimitry Andric #include "llvm/Support/Debug.h" 18*349cc55cSDimitry Andric 19*349cc55cSDimitry Andric #define DEBUG_TYPE "orc" 20*349cc55cSDimitry Andric 21*349cc55cSDimitry Andric using namespace llvm; 22*349cc55cSDimitry Andric using namespace llvm::orc; 23*349cc55cSDimitry Andric using namespace llvm::orc::shared; 24*349cc55cSDimitry Andric 25*349cc55cSDimitry Andric namespace { 26*349cc55cSDimitry Andric 27*349cc55cSDimitry Andric class DSOHandleMaterializationUnit : public MaterializationUnit { 28*349cc55cSDimitry Andric public: 29*349cc55cSDimitry Andric DSOHandleMaterializationUnit(ELFNixPlatform &ENP, 30*349cc55cSDimitry Andric const SymbolStringPtr &DSOHandleSymbol) 31*349cc55cSDimitry Andric : MaterializationUnit(createDSOHandleSectionSymbols(ENP, DSOHandleSymbol), 32*349cc55cSDimitry Andric DSOHandleSymbol), 33*349cc55cSDimitry Andric ENP(ENP) {} 34*349cc55cSDimitry Andric 35*349cc55cSDimitry Andric StringRef getName() const override { return "DSOHandleMU"; } 36*349cc55cSDimitry Andric 37*349cc55cSDimitry Andric void materialize(std::unique_ptr<MaterializationResponsibility> R) override { 38*349cc55cSDimitry Andric unsigned PointerSize; 39*349cc55cSDimitry Andric support::endianness Endianness; 40*349cc55cSDimitry Andric jitlink::Edge::Kind EdgeKind; 41*349cc55cSDimitry Andric const auto &TT = 42*349cc55cSDimitry Andric ENP.getExecutionSession().getExecutorProcessControl().getTargetTriple(); 43*349cc55cSDimitry Andric 44*349cc55cSDimitry Andric switch (TT.getArch()) { 45*349cc55cSDimitry Andric case Triple::x86_64: 46*349cc55cSDimitry Andric PointerSize = 8; 47*349cc55cSDimitry Andric Endianness = support::endianness::little; 48*349cc55cSDimitry Andric EdgeKind = jitlink::x86_64::Pointer64; 49*349cc55cSDimitry Andric break; 50*349cc55cSDimitry Andric default: 51*349cc55cSDimitry Andric llvm_unreachable("Unrecognized architecture"); 52*349cc55cSDimitry Andric } 53*349cc55cSDimitry Andric 54*349cc55cSDimitry Andric // void *__dso_handle = &__dso_handle; 55*349cc55cSDimitry Andric auto G = std::make_unique<jitlink::LinkGraph>( 56*349cc55cSDimitry Andric "<DSOHandleMU>", TT, PointerSize, Endianness, 57*349cc55cSDimitry Andric jitlink::getGenericEdgeKindName); 58*349cc55cSDimitry Andric auto &DSOHandleSection = 59*349cc55cSDimitry Andric G->createSection(".data.__dso_handle", jitlink::MemProt::Read); 60*349cc55cSDimitry Andric auto &DSOHandleBlock = G->createContentBlock( 61*349cc55cSDimitry Andric DSOHandleSection, getDSOHandleContent(PointerSize), 0, 8, 0); 62*349cc55cSDimitry Andric auto &DSOHandleSymbol = G->addDefinedSymbol( 63*349cc55cSDimitry Andric DSOHandleBlock, 0, *R->getInitializerSymbol(), DSOHandleBlock.getSize(), 64*349cc55cSDimitry Andric jitlink::Linkage::Strong, jitlink::Scope::Default, false, true); 65*349cc55cSDimitry Andric DSOHandleBlock.addEdge(EdgeKind, 0, DSOHandleSymbol, 0); 66*349cc55cSDimitry Andric 67*349cc55cSDimitry Andric ENP.getObjectLinkingLayer().emit(std::move(R), std::move(G)); 68*349cc55cSDimitry Andric } 69*349cc55cSDimitry Andric 70*349cc55cSDimitry Andric void discard(const JITDylib &JD, const SymbolStringPtr &Sym) override {} 71*349cc55cSDimitry Andric 72*349cc55cSDimitry Andric private: 73*349cc55cSDimitry Andric static SymbolFlagsMap 74*349cc55cSDimitry Andric createDSOHandleSectionSymbols(ELFNixPlatform &ENP, 75*349cc55cSDimitry Andric const SymbolStringPtr &DSOHandleSymbol) { 76*349cc55cSDimitry Andric SymbolFlagsMap SymbolFlags; 77*349cc55cSDimitry Andric SymbolFlags[DSOHandleSymbol] = JITSymbolFlags::Exported; 78*349cc55cSDimitry Andric return SymbolFlags; 79*349cc55cSDimitry Andric } 80*349cc55cSDimitry Andric 81*349cc55cSDimitry Andric ArrayRef<char> getDSOHandleContent(size_t PointerSize) { 82*349cc55cSDimitry Andric static const char Content[8] = {0}; 83*349cc55cSDimitry Andric assert(PointerSize <= sizeof Content); 84*349cc55cSDimitry Andric return {Content, PointerSize}; 85*349cc55cSDimitry Andric } 86*349cc55cSDimitry Andric 87*349cc55cSDimitry Andric ELFNixPlatform &ENP; 88*349cc55cSDimitry Andric }; 89*349cc55cSDimitry Andric 90*349cc55cSDimitry Andric StringRef EHFrameSectionName = ".eh_frame"; 91*349cc55cSDimitry Andric StringRef InitArrayFuncSectionName = ".init_array"; 92*349cc55cSDimitry Andric 93*349cc55cSDimitry Andric StringRef ThreadBSSSectionName = ".tbss"; 94*349cc55cSDimitry Andric StringRef ThreadDataSectionName = ".tdata"; 95*349cc55cSDimitry Andric 96*349cc55cSDimitry Andric StringRef InitSectionNames[] = {InitArrayFuncSectionName}; 97*349cc55cSDimitry Andric 98*349cc55cSDimitry Andric } // end anonymous namespace 99*349cc55cSDimitry Andric 100*349cc55cSDimitry Andric namespace llvm { 101*349cc55cSDimitry Andric namespace orc { 102*349cc55cSDimitry Andric 103*349cc55cSDimitry Andric Expected<std::unique_ptr<ELFNixPlatform>> 104*349cc55cSDimitry Andric ELFNixPlatform::Create(ExecutionSession &ES, 105*349cc55cSDimitry Andric ObjectLinkingLayer &ObjLinkingLayer, 106*349cc55cSDimitry Andric JITDylib &PlatformJD, const char *OrcRuntimePath, 107*349cc55cSDimitry Andric Optional<SymbolAliasMap> RuntimeAliases) { 108*349cc55cSDimitry Andric 109*349cc55cSDimitry Andric auto &EPC = ES.getExecutorProcessControl(); 110*349cc55cSDimitry Andric 111*349cc55cSDimitry Andric // If the target is not supported then bail out immediately. 112*349cc55cSDimitry Andric if (!supportedTarget(EPC.getTargetTriple())) 113*349cc55cSDimitry Andric return make_error<StringError>("Unsupported ELFNixPlatform triple: " + 114*349cc55cSDimitry Andric EPC.getTargetTriple().str(), 115*349cc55cSDimitry Andric inconvertibleErrorCode()); 116*349cc55cSDimitry Andric 117*349cc55cSDimitry Andric // Create default aliases if the caller didn't supply any. 118*349cc55cSDimitry Andric if (!RuntimeAliases) 119*349cc55cSDimitry Andric RuntimeAliases = standardPlatformAliases(ES); 120*349cc55cSDimitry Andric 121*349cc55cSDimitry Andric // Define the aliases. 122*349cc55cSDimitry Andric if (auto Err = PlatformJD.define(symbolAliases(std::move(*RuntimeAliases)))) 123*349cc55cSDimitry Andric return std::move(Err); 124*349cc55cSDimitry Andric 125*349cc55cSDimitry Andric // Add JIT-dispatch function support symbols. 126*349cc55cSDimitry Andric if (auto Err = PlatformJD.define(absoluteSymbols( 127*349cc55cSDimitry Andric {{ES.intern("__orc_rt_jit_dispatch"), 128*349cc55cSDimitry Andric {EPC.getJITDispatchInfo().JITDispatchFunction.getValue(), 129*349cc55cSDimitry Andric JITSymbolFlags::Exported}}, 130*349cc55cSDimitry Andric {ES.intern("__orc_rt_jit_dispatch_ctx"), 131*349cc55cSDimitry Andric {EPC.getJITDispatchInfo().JITDispatchContext.getValue(), 132*349cc55cSDimitry Andric JITSymbolFlags::Exported}}}))) 133*349cc55cSDimitry Andric return std::move(Err); 134*349cc55cSDimitry Andric 135*349cc55cSDimitry Andric // Create a generator for the ORC runtime archive. 136*349cc55cSDimitry Andric auto OrcRuntimeArchiveGenerator = StaticLibraryDefinitionGenerator::Load( 137*349cc55cSDimitry Andric ObjLinkingLayer, OrcRuntimePath, EPC.getTargetTriple()); 138*349cc55cSDimitry Andric if (!OrcRuntimeArchiveGenerator) 139*349cc55cSDimitry Andric return OrcRuntimeArchiveGenerator.takeError(); 140*349cc55cSDimitry Andric 141*349cc55cSDimitry Andric // Create the instance. 142*349cc55cSDimitry Andric Error Err = Error::success(); 143*349cc55cSDimitry Andric auto P = std::unique_ptr<ELFNixPlatform>( 144*349cc55cSDimitry Andric new ELFNixPlatform(ES, ObjLinkingLayer, PlatformJD, 145*349cc55cSDimitry Andric std::move(*OrcRuntimeArchiveGenerator), Err)); 146*349cc55cSDimitry Andric if (Err) 147*349cc55cSDimitry Andric return std::move(Err); 148*349cc55cSDimitry Andric return std::move(P); 149*349cc55cSDimitry Andric } 150*349cc55cSDimitry Andric 151*349cc55cSDimitry Andric Error ELFNixPlatform::setupJITDylib(JITDylib &JD) { 152*349cc55cSDimitry Andric return JD.define( 153*349cc55cSDimitry Andric std::make_unique<DSOHandleMaterializationUnit>(*this, DSOHandleSymbol)); 154*349cc55cSDimitry Andric } 155*349cc55cSDimitry Andric 156*349cc55cSDimitry Andric Error ELFNixPlatform::notifyAdding(ResourceTracker &RT, 157*349cc55cSDimitry Andric const MaterializationUnit &MU) { 158*349cc55cSDimitry Andric auto &JD = RT.getJITDylib(); 159*349cc55cSDimitry Andric const auto &InitSym = MU.getInitializerSymbol(); 160*349cc55cSDimitry Andric if (!InitSym) 161*349cc55cSDimitry Andric return Error::success(); 162*349cc55cSDimitry Andric 163*349cc55cSDimitry Andric RegisteredInitSymbols[&JD].add(InitSym, 164*349cc55cSDimitry Andric SymbolLookupFlags::WeaklyReferencedSymbol); 165*349cc55cSDimitry Andric LLVM_DEBUG({ 166*349cc55cSDimitry Andric dbgs() << "ELFNixPlatform: Registered init symbol " << *InitSym 167*349cc55cSDimitry Andric << " for MU " << MU.getName() << "\n"; 168*349cc55cSDimitry Andric }); 169*349cc55cSDimitry Andric return Error::success(); 170*349cc55cSDimitry Andric } 171*349cc55cSDimitry Andric 172*349cc55cSDimitry Andric Error ELFNixPlatform::notifyRemoving(ResourceTracker &RT) { 173*349cc55cSDimitry Andric llvm_unreachable("Not supported yet"); 174*349cc55cSDimitry Andric } 175*349cc55cSDimitry Andric 176*349cc55cSDimitry Andric static void addAliases(ExecutionSession &ES, SymbolAliasMap &Aliases, 177*349cc55cSDimitry Andric ArrayRef<std::pair<const char *, const char *>> AL) { 178*349cc55cSDimitry Andric for (auto &KV : AL) { 179*349cc55cSDimitry Andric auto AliasName = ES.intern(KV.first); 180*349cc55cSDimitry Andric assert(!Aliases.count(AliasName) && "Duplicate symbol name in alias map"); 181*349cc55cSDimitry Andric Aliases[std::move(AliasName)] = {ES.intern(KV.second), 182*349cc55cSDimitry Andric JITSymbolFlags::Exported}; 183*349cc55cSDimitry Andric } 184*349cc55cSDimitry Andric } 185*349cc55cSDimitry Andric 186*349cc55cSDimitry Andric SymbolAliasMap ELFNixPlatform::standardPlatformAliases(ExecutionSession &ES) { 187*349cc55cSDimitry Andric SymbolAliasMap Aliases; 188*349cc55cSDimitry Andric addAliases(ES, Aliases, requiredCXXAliases()); 189*349cc55cSDimitry Andric addAliases(ES, Aliases, standardRuntimeUtilityAliases()); 190*349cc55cSDimitry Andric return Aliases; 191*349cc55cSDimitry Andric } 192*349cc55cSDimitry Andric 193*349cc55cSDimitry Andric ArrayRef<std::pair<const char *, const char *>> 194*349cc55cSDimitry Andric ELFNixPlatform::requiredCXXAliases() { 195*349cc55cSDimitry Andric static const std::pair<const char *, const char *> RequiredCXXAliases[] = { 196*349cc55cSDimitry Andric {"__cxa_atexit", "__orc_rt_elfnix_cxa_atexit"}, 197*349cc55cSDimitry Andric {"atexit", "__orc_rt_elfnix_atexit"}}; 198*349cc55cSDimitry Andric 199*349cc55cSDimitry Andric return ArrayRef<std::pair<const char *, const char *>>(RequiredCXXAliases); 200*349cc55cSDimitry Andric } 201*349cc55cSDimitry Andric 202*349cc55cSDimitry Andric ArrayRef<std::pair<const char *, const char *>> 203*349cc55cSDimitry Andric ELFNixPlatform::standardRuntimeUtilityAliases() { 204*349cc55cSDimitry Andric static const std::pair<const char *, const char *> 205*349cc55cSDimitry Andric StandardRuntimeUtilityAliases[] = { 206*349cc55cSDimitry Andric {"__orc_rt_run_program", "__orc_rt_elfnix_run_program"}, 207*349cc55cSDimitry Andric {"__orc_rt_log_error", "__orc_rt_log_error_to_stderr"}}; 208*349cc55cSDimitry Andric 209*349cc55cSDimitry Andric return ArrayRef<std::pair<const char *, const char *>>( 210*349cc55cSDimitry Andric StandardRuntimeUtilityAliases); 211*349cc55cSDimitry Andric } 212*349cc55cSDimitry Andric 213*349cc55cSDimitry Andric bool ELFNixPlatform::isInitializerSection(StringRef SecName) { 214*349cc55cSDimitry Andric for (auto &Name : InitSectionNames) { 215*349cc55cSDimitry Andric if (Name.equals(SecName)) 216*349cc55cSDimitry Andric return true; 217*349cc55cSDimitry Andric } 218*349cc55cSDimitry Andric return false; 219*349cc55cSDimitry Andric } 220*349cc55cSDimitry Andric 221*349cc55cSDimitry Andric bool ELFNixPlatform::supportedTarget(const Triple &TT) { 222*349cc55cSDimitry Andric switch (TT.getArch()) { 223*349cc55cSDimitry Andric case Triple::x86_64: 224*349cc55cSDimitry Andric return true; 225*349cc55cSDimitry Andric default: 226*349cc55cSDimitry Andric return false; 227*349cc55cSDimitry Andric } 228*349cc55cSDimitry Andric } 229*349cc55cSDimitry Andric 230*349cc55cSDimitry Andric ELFNixPlatform::ELFNixPlatform( 231*349cc55cSDimitry Andric ExecutionSession &ES, ObjectLinkingLayer &ObjLinkingLayer, 232*349cc55cSDimitry Andric JITDylib &PlatformJD, 233*349cc55cSDimitry Andric std::unique_ptr<DefinitionGenerator> OrcRuntimeGenerator, Error &Err) 234*349cc55cSDimitry Andric : ES(ES), ObjLinkingLayer(ObjLinkingLayer), 235*349cc55cSDimitry Andric DSOHandleSymbol(ES.intern("__dso_handle")) { 236*349cc55cSDimitry Andric ErrorAsOutParameter _(&Err); 237*349cc55cSDimitry Andric 238*349cc55cSDimitry Andric ObjLinkingLayer.addPlugin(std::make_unique<ELFNixPlatformPlugin>(*this)); 239*349cc55cSDimitry Andric 240*349cc55cSDimitry Andric PlatformJD.addGenerator(std::move(OrcRuntimeGenerator)); 241*349cc55cSDimitry Andric 242*349cc55cSDimitry Andric // PlatformJD hasn't been 'set-up' by the platform yet (since we're creating 243*349cc55cSDimitry Andric // the platform now), so set it up. 244*349cc55cSDimitry Andric if (auto E2 = setupJITDylib(PlatformJD)) { 245*349cc55cSDimitry Andric Err = std::move(E2); 246*349cc55cSDimitry Andric return; 247*349cc55cSDimitry Andric } 248*349cc55cSDimitry Andric 249*349cc55cSDimitry Andric RegisteredInitSymbols[&PlatformJD].add( 250*349cc55cSDimitry Andric DSOHandleSymbol, SymbolLookupFlags::WeaklyReferencedSymbol); 251*349cc55cSDimitry Andric 252*349cc55cSDimitry Andric // Associate wrapper function tags with JIT-side function implementations. 253*349cc55cSDimitry Andric if (auto E2 = associateRuntimeSupportFunctions(PlatformJD)) { 254*349cc55cSDimitry Andric Err = std::move(E2); 255*349cc55cSDimitry Andric return; 256*349cc55cSDimitry Andric } 257*349cc55cSDimitry Andric 258*349cc55cSDimitry Andric // Lookup addresses of runtime functions callable by the platform, 259*349cc55cSDimitry Andric // call the platform bootstrap function to initialize the platform-state 260*349cc55cSDimitry Andric // object in the executor. 261*349cc55cSDimitry Andric if (auto E2 = bootstrapELFNixRuntime(PlatformJD)) { 262*349cc55cSDimitry Andric Err = std::move(E2); 263*349cc55cSDimitry Andric return; 264*349cc55cSDimitry Andric } 265*349cc55cSDimitry Andric } 266*349cc55cSDimitry Andric 267*349cc55cSDimitry Andric Error ELFNixPlatform::associateRuntimeSupportFunctions(JITDylib &PlatformJD) { 268*349cc55cSDimitry Andric ExecutionSession::JITDispatchHandlerAssociationMap WFs; 269*349cc55cSDimitry Andric 270*349cc55cSDimitry Andric using GetInitializersSPSSig = 271*349cc55cSDimitry Andric SPSExpected<SPSELFNixJITDylibInitializerSequence>(SPSString); 272*349cc55cSDimitry Andric WFs[ES.intern("__orc_rt_elfnix_get_initializers_tag")] = 273*349cc55cSDimitry Andric ES.wrapAsyncWithSPS<GetInitializersSPSSig>( 274*349cc55cSDimitry Andric this, &ELFNixPlatform::rt_getInitializers); 275*349cc55cSDimitry Andric 276*349cc55cSDimitry Andric using GetDeinitializersSPSSig = 277*349cc55cSDimitry Andric SPSExpected<SPSELFJITDylibDeinitializerSequence>(SPSExecutorAddr); 278*349cc55cSDimitry Andric WFs[ES.intern("__orc_rt_elfnix_get_deinitializers_tag")] = 279*349cc55cSDimitry Andric ES.wrapAsyncWithSPS<GetDeinitializersSPSSig>( 280*349cc55cSDimitry Andric this, &ELFNixPlatform::rt_getDeinitializers); 281*349cc55cSDimitry Andric 282*349cc55cSDimitry Andric using LookupSymbolSPSSig = 283*349cc55cSDimitry Andric SPSExpected<SPSExecutorAddr>(SPSExecutorAddr, SPSString); 284*349cc55cSDimitry Andric WFs[ES.intern("__orc_rt_elfnix_symbol_lookup_tag")] = 285*349cc55cSDimitry Andric ES.wrapAsyncWithSPS<LookupSymbolSPSSig>(this, 286*349cc55cSDimitry Andric &ELFNixPlatform::rt_lookupSymbol); 287*349cc55cSDimitry Andric 288*349cc55cSDimitry Andric return ES.registerJITDispatchHandlers(PlatformJD, std::move(WFs)); 289*349cc55cSDimitry Andric } 290*349cc55cSDimitry Andric 291*349cc55cSDimitry Andric void ELFNixPlatform::getInitializersBuildSequencePhase( 292*349cc55cSDimitry Andric SendInitializerSequenceFn SendResult, JITDylib &JD, 293*349cc55cSDimitry Andric std::vector<JITDylibSP> DFSLinkOrder) { 294*349cc55cSDimitry Andric ELFNixJITDylibInitializerSequence FullInitSeq; 295*349cc55cSDimitry Andric { 296*349cc55cSDimitry Andric std::lock_guard<std::mutex> Lock(PlatformMutex); 297*349cc55cSDimitry Andric for (auto &InitJD : reverse(DFSLinkOrder)) { 298*349cc55cSDimitry Andric LLVM_DEBUG({ 299*349cc55cSDimitry Andric dbgs() << "ELFNixPlatform: Appending inits for \"" << InitJD->getName() 300*349cc55cSDimitry Andric << "\" to sequence\n"; 301*349cc55cSDimitry Andric }); 302*349cc55cSDimitry Andric auto ISItr = InitSeqs.find(InitJD.get()); 303*349cc55cSDimitry Andric if (ISItr != InitSeqs.end()) { 304*349cc55cSDimitry Andric FullInitSeq.emplace_back(std::move(ISItr->second)); 305*349cc55cSDimitry Andric InitSeqs.erase(ISItr); 306*349cc55cSDimitry Andric } 307*349cc55cSDimitry Andric } 308*349cc55cSDimitry Andric } 309*349cc55cSDimitry Andric 310*349cc55cSDimitry Andric SendResult(std::move(FullInitSeq)); 311*349cc55cSDimitry Andric } 312*349cc55cSDimitry Andric 313*349cc55cSDimitry Andric void ELFNixPlatform::getInitializersLookupPhase( 314*349cc55cSDimitry Andric SendInitializerSequenceFn SendResult, JITDylib &JD) { 315*349cc55cSDimitry Andric 316*349cc55cSDimitry Andric auto DFSLinkOrder = JD.getDFSLinkOrder(); 317*349cc55cSDimitry Andric DenseMap<JITDylib *, SymbolLookupSet> NewInitSymbols; 318*349cc55cSDimitry Andric ES.runSessionLocked([&]() { 319*349cc55cSDimitry Andric for (auto &InitJD : DFSLinkOrder) { 320*349cc55cSDimitry Andric auto RISItr = RegisteredInitSymbols.find(InitJD.get()); 321*349cc55cSDimitry Andric if (RISItr != RegisteredInitSymbols.end()) { 322*349cc55cSDimitry Andric NewInitSymbols[InitJD.get()] = std::move(RISItr->second); 323*349cc55cSDimitry Andric RegisteredInitSymbols.erase(RISItr); 324*349cc55cSDimitry Andric } 325*349cc55cSDimitry Andric } 326*349cc55cSDimitry Andric }); 327*349cc55cSDimitry Andric 328*349cc55cSDimitry Andric // If there are no further init symbols to look up then move on to the next 329*349cc55cSDimitry Andric // phase. 330*349cc55cSDimitry Andric if (NewInitSymbols.empty()) { 331*349cc55cSDimitry Andric getInitializersBuildSequencePhase(std::move(SendResult), JD, 332*349cc55cSDimitry Andric std::move(DFSLinkOrder)); 333*349cc55cSDimitry Andric return; 334*349cc55cSDimitry Andric } 335*349cc55cSDimitry Andric 336*349cc55cSDimitry Andric // Otherwise issue a lookup and re-run this phase when it completes. 337*349cc55cSDimitry Andric lookupInitSymbolsAsync( 338*349cc55cSDimitry Andric [this, SendResult = std::move(SendResult), &JD](Error Err) mutable { 339*349cc55cSDimitry Andric if (Err) 340*349cc55cSDimitry Andric SendResult(std::move(Err)); 341*349cc55cSDimitry Andric else 342*349cc55cSDimitry Andric getInitializersLookupPhase(std::move(SendResult), JD); 343*349cc55cSDimitry Andric }, 344*349cc55cSDimitry Andric ES, std::move(NewInitSymbols)); 345*349cc55cSDimitry Andric } 346*349cc55cSDimitry Andric 347*349cc55cSDimitry Andric void ELFNixPlatform::rt_getInitializers(SendInitializerSequenceFn SendResult, 348*349cc55cSDimitry Andric StringRef JDName) { 349*349cc55cSDimitry Andric LLVM_DEBUG({ 350*349cc55cSDimitry Andric dbgs() << "ELFNixPlatform::rt_getInitializers(\"" << JDName << "\")\n"; 351*349cc55cSDimitry Andric }); 352*349cc55cSDimitry Andric 353*349cc55cSDimitry Andric JITDylib *JD = ES.getJITDylibByName(JDName); 354*349cc55cSDimitry Andric if (!JD) { 355*349cc55cSDimitry Andric LLVM_DEBUG({ 356*349cc55cSDimitry Andric dbgs() << " No such JITDylib \"" << JDName << "\". Sending error.\n"; 357*349cc55cSDimitry Andric }); 358*349cc55cSDimitry Andric SendResult(make_error<StringError>("No JITDylib named " + JDName, 359*349cc55cSDimitry Andric inconvertibleErrorCode())); 360*349cc55cSDimitry Andric return; 361*349cc55cSDimitry Andric } 362*349cc55cSDimitry Andric 363*349cc55cSDimitry Andric getInitializersLookupPhase(std::move(SendResult), *JD); 364*349cc55cSDimitry Andric } 365*349cc55cSDimitry Andric 366*349cc55cSDimitry Andric void ELFNixPlatform::rt_getDeinitializers( 367*349cc55cSDimitry Andric SendDeinitializerSequenceFn SendResult, ExecutorAddr Handle) { 368*349cc55cSDimitry Andric LLVM_DEBUG({ 369*349cc55cSDimitry Andric dbgs() << "ELFNixPlatform::rt_getDeinitializers(\"" 370*349cc55cSDimitry Andric << formatv("{0:x}", Handle.getValue()) << "\")\n"; 371*349cc55cSDimitry Andric }); 372*349cc55cSDimitry Andric 373*349cc55cSDimitry Andric JITDylib *JD = nullptr; 374*349cc55cSDimitry Andric 375*349cc55cSDimitry Andric { 376*349cc55cSDimitry Andric std::lock_guard<std::mutex> Lock(PlatformMutex); 377*349cc55cSDimitry Andric auto I = HandleAddrToJITDylib.find(Handle.getValue()); 378*349cc55cSDimitry Andric if (I != HandleAddrToJITDylib.end()) 379*349cc55cSDimitry Andric JD = I->second; 380*349cc55cSDimitry Andric } 381*349cc55cSDimitry Andric 382*349cc55cSDimitry Andric if (!JD) { 383*349cc55cSDimitry Andric LLVM_DEBUG({ 384*349cc55cSDimitry Andric dbgs() << " No JITDylib for handle " 385*349cc55cSDimitry Andric << formatv("{0:x}", Handle.getValue()) << "\n"; 386*349cc55cSDimitry Andric }); 387*349cc55cSDimitry Andric SendResult(make_error<StringError>("No JITDylib associated with handle " + 388*349cc55cSDimitry Andric formatv("{0:x}", Handle.getValue()), 389*349cc55cSDimitry Andric inconvertibleErrorCode())); 390*349cc55cSDimitry Andric return; 391*349cc55cSDimitry Andric } 392*349cc55cSDimitry Andric 393*349cc55cSDimitry Andric SendResult(ELFNixJITDylibDeinitializerSequence()); 394*349cc55cSDimitry Andric } 395*349cc55cSDimitry Andric 396*349cc55cSDimitry Andric void ELFNixPlatform::rt_lookupSymbol(SendSymbolAddressFn SendResult, 397*349cc55cSDimitry Andric ExecutorAddr Handle, 398*349cc55cSDimitry Andric StringRef SymbolName) { 399*349cc55cSDimitry Andric LLVM_DEBUG({ 400*349cc55cSDimitry Andric dbgs() << "ELFNixPlatform::rt_lookupSymbol(\"" 401*349cc55cSDimitry Andric << formatv("{0:x}", Handle.getValue()) << "\")\n"; 402*349cc55cSDimitry Andric }); 403*349cc55cSDimitry Andric 404*349cc55cSDimitry Andric JITDylib *JD = nullptr; 405*349cc55cSDimitry Andric 406*349cc55cSDimitry Andric { 407*349cc55cSDimitry Andric std::lock_guard<std::mutex> Lock(PlatformMutex); 408*349cc55cSDimitry Andric auto I = HandleAddrToJITDylib.find(Handle.getValue()); 409*349cc55cSDimitry Andric if (I != HandleAddrToJITDylib.end()) 410*349cc55cSDimitry Andric JD = I->second; 411*349cc55cSDimitry Andric } 412*349cc55cSDimitry Andric 413*349cc55cSDimitry Andric if (!JD) { 414*349cc55cSDimitry Andric LLVM_DEBUG({ 415*349cc55cSDimitry Andric dbgs() << " No JITDylib for handle " 416*349cc55cSDimitry Andric << formatv("{0:x}", Handle.getValue()) << "\n"; 417*349cc55cSDimitry Andric }); 418*349cc55cSDimitry Andric SendResult(make_error<StringError>("No JITDylib associated with handle " + 419*349cc55cSDimitry Andric formatv("{0:x}", Handle.getValue()), 420*349cc55cSDimitry Andric inconvertibleErrorCode())); 421*349cc55cSDimitry Andric return; 422*349cc55cSDimitry Andric } 423*349cc55cSDimitry Andric 424*349cc55cSDimitry Andric // Use functor class to work around XL build compiler issue on AIX. 425*349cc55cSDimitry Andric class RtLookupNotifyComplete { 426*349cc55cSDimitry Andric public: 427*349cc55cSDimitry Andric RtLookupNotifyComplete(SendSymbolAddressFn &&SendResult) 428*349cc55cSDimitry Andric : SendResult(std::move(SendResult)) {} 429*349cc55cSDimitry Andric void operator()(Expected<SymbolMap> Result) { 430*349cc55cSDimitry Andric if (Result) { 431*349cc55cSDimitry Andric assert(Result->size() == 1 && "Unexpected result map count"); 432*349cc55cSDimitry Andric SendResult(ExecutorAddr(Result->begin()->second.getAddress())); 433*349cc55cSDimitry Andric } else { 434*349cc55cSDimitry Andric SendResult(Result.takeError()); 435*349cc55cSDimitry Andric } 436*349cc55cSDimitry Andric } 437*349cc55cSDimitry Andric 438*349cc55cSDimitry Andric private: 439*349cc55cSDimitry Andric SendSymbolAddressFn SendResult; 440*349cc55cSDimitry Andric }; 441*349cc55cSDimitry Andric 442*349cc55cSDimitry Andric ES.lookup( 443*349cc55cSDimitry Andric LookupKind::DLSym, {{JD, JITDylibLookupFlags::MatchExportedSymbolsOnly}}, 444*349cc55cSDimitry Andric SymbolLookupSet(ES.intern(SymbolName)), SymbolState::Ready, 445*349cc55cSDimitry Andric RtLookupNotifyComplete(std::move(SendResult)), NoDependenciesToRegister); 446*349cc55cSDimitry Andric } 447*349cc55cSDimitry Andric 448*349cc55cSDimitry Andric Error ELFNixPlatform::bootstrapELFNixRuntime(JITDylib &PlatformJD) { 449*349cc55cSDimitry Andric 450*349cc55cSDimitry Andric std::pair<const char *, ExecutorAddr *> Symbols[] = { 451*349cc55cSDimitry Andric {"__orc_rt_elfnix_platform_bootstrap", &orc_rt_elfnix_platform_bootstrap}, 452*349cc55cSDimitry Andric {"__orc_rt_elfnix_platform_shutdown", &orc_rt_elfnix_platform_shutdown}, 453*349cc55cSDimitry Andric {"__orc_rt_elfnix_register_object_sections", 454*349cc55cSDimitry Andric &orc_rt_elfnix_register_object_sections}, 455*349cc55cSDimitry Andric {"__orc_rt_elfnix_create_pthread_key", 456*349cc55cSDimitry Andric &orc_rt_elfnix_create_pthread_key}}; 457*349cc55cSDimitry Andric 458*349cc55cSDimitry Andric SymbolLookupSet RuntimeSymbols; 459*349cc55cSDimitry Andric std::vector<std::pair<SymbolStringPtr, ExecutorAddr *>> AddrsToRecord; 460*349cc55cSDimitry Andric for (const auto &KV : Symbols) { 461*349cc55cSDimitry Andric auto Name = ES.intern(KV.first); 462*349cc55cSDimitry Andric RuntimeSymbols.add(Name); 463*349cc55cSDimitry Andric AddrsToRecord.push_back({std::move(Name), KV.second}); 464*349cc55cSDimitry Andric } 465*349cc55cSDimitry Andric 466*349cc55cSDimitry Andric auto RuntimeSymbolAddrs = ES.lookup( 467*349cc55cSDimitry Andric {{&PlatformJD, JITDylibLookupFlags::MatchAllSymbols}}, RuntimeSymbols); 468*349cc55cSDimitry Andric if (!RuntimeSymbolAddrs) 469*349cc55cSDimitry Andric return RuntimeSymbolAddrs.takeError(); 470*349cc55cSDimitry Andric 471*349cc55cSDimitry Andric for (const auto &KV : AddrsToRecord) { 472*349cc55cSDimitry Andric auto &Name = KV.first; 473*349cc55cSDimitry Andric assert(RuntimeSymbolAddrs->count(Name) && "Missing runtime symbol?"); 474*349cc55cSDimitry Andric KV.second->setValue((*RuntimeSymbolAddrs)[Name].getAddress()); 475*349cc55cSDimitry Andric } 476*349cc55cSDimitry Andric 477*349cc55cSDimitry Andric auto PJDDSOHandle = ES.lookup( 478*349cc55cSDimitry Andric {{&PlatformJD, JITDylibLookupFlags::MatchAllSymbols}}, DSOHandleSymbol); 479*349cc55cSDimitry Andric if (!PJDDSOHandle) 480*349cc55cSDimitry Andric return PJDDSOHandle.takeError(); 481*349cc55cSDimitry Andric 482*349cc55cSDimitry Andric if (auto Err = ES.callSPSWrapper<void(uint64_t)>( 483*349cc55cSDimitry Andric orc_rt_elfnix_platform_bootstrap, PJDDSOHandle->getAddress())) 484*349cc55cSDimitry Andric return Err; 485*349cc55cSDimitry Andric 486*349cc55cSDimitry Andric // FIXME: Ordering is fuzzy here. We're probably best off saying 487*349cc55cSDimitry Andric // "behavior is undefined if code that uses the runtime is added before 488*349cc55cSDimitry Andric // the platform constructor returns", then move all this to the constructor. 489*349cc55cSDimitry Andric RuntimeBootstrapped = true; 490*349cc55cSDimitry Andric std::vector<ELFPerObjectSectionsToRegister> DeferredPOSRs; 491*349cc55cSDimitry Andric { 492*349cc55cSDimitry Andric std::lock_guard<std::mutex> Lock(PlatformMutex); 493*349cc55cSDimitry Andric DeferredPOSRs = std::move(BootstrapPOSRs); 494*349cc55cSDimitry Andric } 495*349cc55cSDimitry Andric 496*349cc55cSDimitry Andric for (auto &D : DeferredPOSRs) 497*349cc55cSDimitry Andric if (auto Err = registerPerObjectSections(D)) 498*349cc55cSDimitry Andric return Err; 499*349cc55cSDimitry Andric 500*349cc55cSDimitry Andric return Error::success(); 501*349cc55cSDimitry Andric } 502*349cc55cSDimitry Andric 503*349cc55cSDimitry Andric Error ELFNixPlatform::registerInitInfo( 504*349cc55cSDimitry Andric JITDylib &JD, ArrayRef<jitlink::Section *> InitSections) { 505*349cc55cSDimitry Andric 506*349cc55cSDimitry Andric std::unique_lock<std::mutex> Lock(PlatformMutex); 507*349cc55cSDimitry Andric 508*349cc55cSDimitry Andric ELFNixJITDylibInitializers *InitSeq = nullptr; 509*349cc55cSDimitry Andric { 510*349cc55cSDimitry Andric auto I = InitSeqs.find(&JD); 511*349cc55cSDimitry Andric if (I == InitSeqs.end()) { 512*349cc55cSDimitry Andric // If there's no init sequence entry yet then we need to look up the 513*349cc55cSDimitry Andric // header symbol to force creation of one. 514*349cc55cSDimitry Andric Lock.unlock(); 515*349cc55cSDimitry Andric 516*349cc55cSDimitry Andric auto SearchOrder = 517*349cc55cSDimitry Andric JD.withLinkOrderDo([](const JITDylibSearchOrder &SO) { return SO; }); 518*349cc55cSDimitry Andric if (auto Err = ES.lookup(SearchOrder, DSOHandleSymbol).takeError()) 519*349cc55cSDimitry Andric return Err; 520*349cc55cSDimitry Andric 521*349cc55cSDimitry Andric Lock.lock(); 522*349cc55cSDimitry Andric I = InitSeqs.find(&JD); 523*349cc55cSDimitry Andric assert(I != InitSeqs.end() && 524*349cc55cSDimitry Andric "Entry missing after header symbol lookup?"); 525*349cc55cSDimitry Andric } 526*349cc55cSDimitry Andric InitSeq = &I->second; 527*349cc55cSDimitry Andric } 528*349cc55cSDimitry Andric 529*349cc55cSDimitry Andric for (auto *Sec : InitSections) { 530*349cc55cSDimitry Andric // FIXME: Avoid copy here. 531*349cc55cSDimitry Andric jitlink::SectionRange R(*Sec); 532*349cc55cSDimitry Andric InitSeq->InitSections[Sec->getName()].push_back( 533*349cc55cSDimitry Andric {ExecutorAddr(R.getStart()), ExecutorAddr(R.getEnd())}); 534*349cc55cSDimitry Andric } 535*349cc55cSDimitry Andric 536*349cc55cSDimitry Andric return Error::success(); 537*349cc55cSDimitry Andric } 538*349cc55cSDimitry Andric 539*349cc55cSDimitry Andric Error ELFNixPlatform::registerPerObjectSections( 540*349cc55cSDimitry Andric const ELFPerObjectSectionsToRegister &POSR) { 541*349cc55cSDimitry Andric 542*349cc55cSDimitry Andric if (!orc_rt_elfnix_register_object_sections) 543*349cc55cSDimitry Andric return make_error<StringError>("Attempting to register per-object " 544*349cc55cSDimitry Andric "sections, but runtime support has not " 545*349cc55cSDimitry Andric "been loaded yet", 546*349cc55cSDimitry Andric inconvertibleErrorCode()); 547*349cc55cSDimitry Andric 548*349cc55cSDimitry Andric Error ErrResult = Error::success(); 549*349cc55cSDimitry Andric if (auto Err = ES.callSPSWrapper<shared::SPSError( 550*349cc55cSDimitry Andric SPSELFPerObjectSectionsToRegister)>( 551*349cc55cSDimitry Andric orc_rt_elfnix_register_object_sections, ErrResult, POSR)) 552*349cc55cSDimitry Andric return Err; 553*349cc55cSDimitry Andric return ErrResult; 554*349cc55cSDimitry Andric } 555*349cc55cSDimitry Andric 556*349cc55cSDimitry Andric Expected<uint64_t> ELFNixPlatform::createPThreadKey() { 557*349cc55cSDimitry Andric if (!orc_rt_elfnix_create_pthread_key) 558*349cc55cSDimitry Andric return make_error<StringError>( 559*349cc55cSDimitry Andric "Attempting to create pthread key in target, but runtime support has " 560*349cc55cSDimitry Andric "not been loaded yet", 561*349cc55cSDimitry Andric inconvertibleErrorCode()); 562*349cc55cSDimitry Andric 563*349cc55cSDimitry Andric Expected<uint64_t> Result(0); 564*349cc55cSDimitry Andric if (auto Err = ES.callSPSWrapper<SPSExpected<uint64_t>(void)>( 565*349cc55cSDimitry Andric orc_rt_elfnix_create_pthread_key, Result)) 566*349cc55cSDimitry Andric return std::move(Err); 567*349cc55cSDimitry Andric return Result; 568*349cc55cSDimitry Andric } 569*349cc55cSDimitry Andric 570*349cc55cSDimitry Andric void ELFNixPlatform::ELFNixPlatformPlugin::modifyPassConfig( 571*349cc55cSDimitry Andric MaterializationResponsibility &MR, jitlink::LinkGraph &LG, 572*349cc55cSDimitry Andric jitlink::PassConfiguration &Config) { 573*349cc55cSDimitry Andric 574*349cc55cSDimitry Andric // If the initializer symbol is the __dso_handle symbol then just add 575*349cc55cSDimitry Andric // the DSO handle support passes. 576*349cc55cSDimitry Andric if (MR.getInitializerSymbol() == MP.DSOHandleSymbol) { 577*349cc55cSDimitry Andric addDSOHandleSupportPasses(MR, Config); 578*349cc55cSDimitry Andric // The DSOHandle materialization unit doesn't require any other 579*349cc55cSDimitry Andric // support, so we can bail out early. 580*349cc55cSDimitry Andric return; 581*349cc55cSDimitry Andric } 582*349cc55cSDimitry Andric 583*349cc55cSDimitry Andric // If the object contains initializers then add passes to record them. 584*349cc55cSDimitry Andric if (MR.getInitializerSymbol()) 585*349cc55cSDimitry Andric addInitializerSupportPasses(MR, Config); 586*349cc55cSDimitry Andric 587*349cc55cSDimitry Andric // Add passes for eh-frame and TLV support. 588*349cc55cSDimitry Andric addEHAndTLVSupportPasses(MR, Config); 589*349cc55cSDimitry Andric } 590*349cc55cSDimitry Andric 591*349cc55cSDimitry Andric ObjectLinkingLayer::Plugin::SyntheticSymbolDependenciesMap 592*349cc55cSDimitry Andric ELFNixPlatform::ELFNixPlatformPlugin::getSyntheticSymbolDependencies( 593*349cc55cSDimitry Andric MaterializationResponsibility &MR) { 594*349cc55cSDimitry Andric std::lock_guard<std::mutex> Lock(PluginMutex); 595*349cc55cSDimitry Andric auto I = InitSymbolDeps.find(&MR); 596*349cc55cSDimitry Andric if (I != InitSymbolDeps.end()) { 597*349cc55cSDimitry Andric SyntheticSymbolDependenciesMap Result; 598*349cc55cSDimitry Andric Result[MR.getInitializerSymbol()] = std::move(I->second); 599*349cc55cSDimitry Andric InitSymbolDeps.erase(&MR); 600*349cc55cSDimitry Andric return Result; 601*349cc55cSDimitry Andric } 602*349cc55cSDimitry Andric return SyntheticSymbolDependenciesMap(); 603*349cc55cSDimitry Andric } 604*349cc55cSDimitry Andric 605*349cc55cSDimitry Andric void ELFNixPlatform::ELFNixPlatformPlugin::addInitializerSupportPasses( 606*349cc55cSDimitry Andric MaterializationResponsibility &MR, jitlink::PassConfiguration &Config) { 607*349cc55cSDimitry Andric 608*349cc55cSDimitry Andric /// Preserve init sections. 609*349cc55cSDimitry Andric Config.PrePrunePasses.push_back([this, &MR](jitlink::LinkGraph &G) -> Error { 610*349cc55cSDimitry Andric if (auto Err = preserveInitSections(G, MR)) 611*349cc55cSDimitry Andric return Err; 612*349cc55cSDimitry Andric return Error::success(); 613*349cc55cSDimitry Andric }); 614*349cc55cSDimitry Andric 615*349cc55cSDimitry Andric Config.PostFixupPasses.push_back( 616*349cc55cSDimitry Andric [this, &JD = MR.getTargetJITDylib()](jitlink::LinkGraph &G) { 617*349cc55cSDimitry Andric return registerInitSections(G, JD); 618*349cc55cSDimitry Andric }); 619*349cc55cSDimitry Andric } 620*349cc55cSDimitry Andric 621*349cc55cSDimitry Andric void ELFNixPlatform::ELFNixPlatformPlugin::addDSOHandleSupportPasses( 622*349cc55cSDimitry Andric MaterializationResponsibility &MR, jitlink::PassConfiguration &Config) { 623*349cc55cSDimitry Andric 624*349cc55cSDimitry Andric Config.PostAllocationPasses.push_back([this, &JD = MR.getTargetJITDylib()]( 625*349cc55cSDimitry Andric jitlink::LinkGraph &G) -> Error { 626*349cc55cSDimitry Andric auto I = llvm::find_if(G.defined_symbols(), [this](jitlink::Symbol *Sym) { 627*349cc55cSDimitry Andric return Sym->getName() == *MP.DSOHandleSymbol; 628*349cc55cSDimitry Andric }); 629*349cc55cSDimitry Andric assert(I != G.defined_symbols().end() && "Missing DSO handle symbol"); 630*349cc55cSDimitry Andric { 631*349cc55cSDimitry Andric std::lock_guard<std::mutex> Lock(MP.PlatformMutex); 632*349cc55cSDimitry Andric JITTargetAddress HandleAddr = (*I)->getAddress(); 633*349cc55cSDimitry Andric MP.HandleAddrToJITDylib[HandleAddr] = &JD; 634*349cc55cSDimitry Andric assert(!MP.InitSeqs.count(&JD) && "InitSeq entry for JD already exists"); 635*349cc55cSDimitry Andric MP.InitSeqs.insert(std::make_pair( 636*349cc55cSDimitry Andric &JD, 637*349cc55cSDimitry Andric ELFNixJITDylibInitializers(JD.getName(), ExecutorAddr(HandleAddr)))); 638*349cc55cSDimitry Andric } 639*349cc55cSDimitry Andric return Error::success(); 640*349cc55cSDimitry Andric }); 641*349cc55cSDimitry Andric } 642*349cc55cSDimitry Andric 643*349cc55cSDimitry Andric void ELFNixPlatform::ELFNixPlatformPlugin::addEHAndTLVSupportPasses( 644*349cc55cSDimitry Andric MaterializationResponsibility &MR, jitlink::PassConfiguration &Config) { 645*349cc55cSDimitry Andric 646*349cc55cSDimitry Andric // Insert TLV lowering at the start of the PostPrunePasses, since we want 647*349cc55cSDimitry Andric // it to run before GOT/PLT lowering. 648*349cc55cSDimitry Andric 649*349cc55cSDimitry Andric // TODO: Check that before the fixTLVSectionsAndEdges pass, the GOT/PLT build 650*349cc55cSDimitry Andric // pass has done. Because the TLS descriptor need to be allocate in GOT. 651*349cc55cSDimitry Andric Config.PostPrunePasses.push_back( 652*349cc55cSDimitry Andric [this, &JD = MR.getTargetJITDylib()](jitlink::LinkGraph &G) { 653*349cc55cSDimitry Andric return fixTLVSectionsAndEdges(G, JD); 654*349cc55cSDimitry Andric }); 655*349cc55cSDimitry Andric 656*349cc55cSDimitry Andric // Add a pass to register the final addresses of the eh-frame and TLV sections 657*349cc55cSDimitry Andric // with the runtime. 658*349cc55cSDimitry Andric Config.PostFixupPasses.push_back([this](jitlink::LinkGraph &G) -> Error { 659*349cc55cSDimitry Andric ELFPerObjectSectionsToRegister POSR; 660*349cc55cSDimitry Andric 661*349cc55cSDimitry Andric if (auto *EHFrameSection = G.findSectionByName(EHFrameSectionName)) { 662*349cc55cSDimitry Andric jitlink::SectionRange R(*EHFrameSection); 663*349cc55cSDimitry Andric if (!R.empty()) 664*349cc55cSDimitry Andric POSR.EHFrameSection = {ExecutorAddr(R.getStart()), 665*349cc55cSDimitry Andric ExecutorAddr(R.getEnd())}; 666*349cc55cSDimitry Andric } 667*349cc55cSDimitry Andric 668*349cc55cSDimitry Andric // Get a pointer to the thread data section if there is one. It will be used 669*349cc55cSDimitry Andric // below. 670*349cc55cSDimitry Andric jitlink::Section *ThreadDataSection = 671*349cc55cSDimitry Andric G.findSectionByName(ThreadDataSectionName); 672*349cc55cSDimitry Andric 673*349cc55cSDimitry Andric // Handle thread BSS section if there is one. 674*349cc55cSDimitry Andric if (auto *ThreadBSSSection = G.findSectionByName(ThreadBSSSectionName)) { 675*349cc55cSDimitry Andric // If there's already a thread data section in this graph then merge the 676*349cc55cSDimitry Andric // thread BSS section content into it, otherwise just treat the thread 677*349cc55cSDimitry Andric // BSS section as the thread data section. 678*349cc55cSDimitry Andric if (ThreadDataSection) 679*349cc55cSDimitry Andric G.mergeSections(*ThreadDataSection, *ThreadBSSSection); 680*349cc55cSDimitry Andric else 681*349cc55cSDimitry Andric ThreadDataSection = ThreadBSSSection; 682*349cc55cSDimitry Andric } 683*349cc55cSDimitry Andric 684*349cc55cSDimitry Andric // Having merged thread BSS (if present) and thread data (if present), 685*349cc55cSDimitry Andric // record the resulting section range. 686*349cc55cSDimitry Andric if (ThreadDataSection) { 687*349cc55cSDimitry Andric jitlink::SectionRange R(*ThreadDataSection); 688*349cc55cSDimitry Andric if (!R.empty()) 689*349cc55cSDimitry Andric POSR.ThreadDataSection = {ExecutorAddr(R.getStart()), 690*349cc55cSDimitry Andric ExecutorAddr(R.getEnd())}; 691*349cc55cSDimitry Andric } 692*349cc55cSDimitry Andric 693*349cc55cSDimitry Andric if (POSR.EHFrameSection.Start || POSR.ThreadDataSection.Start) { 694*349cc55cSDimitry Andric 695*349cc55cSDimitry Andric // If we're still bootstrapping the runtime then just record this 696*349cc55cSDimitry Andric // frame for now. 697*349cc55cSDimitry Andric if (!MP.RuntimeBootstrapped) { 698*349cc55cSDimitry Andric std::lock_guard<std::mutex> Lock(MP.PlatformMutex); 699*349cc55cSDimitry Andric MP.BootstrapPOSRs.push_back(POSR); 700*349cc55cSDimitry Andric return Error::success(); 701*349cc55cSDimitry Andric } 702*349cc55cSDimitry Andric 703*349cc55cSDimitry Andric // Otherwise register it immediately. 704*349cc55cSDimitry Andric if (auto Err = MP.registerPerObjectSections(POSR)) 705*349cc55cSDimitry Andric return Err; 706*349cc55cSDimitry Andric } 707*349cc55cSDimitry Andric 708*349cc55cSDimitry Andric return Error::success(); 709*349cc55cSDimitry Andric }); 710*349cc55cSDimitry Andric } 711*349cc55cSDimitry Andric 712*349cc55cSDimitry Andric Error ELFNixPlatform::ELFNixPlatformPlugin::preserveInitSections( 713*349cc55cSDimitry Andric jitlink::LinkGraph &G, MaterializationResponsibility &MR) { 714*349cc55cSDimitry Andric 715*349cc55cSDimitry Andric JITLinkSymbolSet InitSectionSymbols; 716*349cc55cSDimitry Andric for (auto &InitSectionName : InitSectionNames) { 717*349cc55cSDimitry Andric // Skip non-init sections. 718*349cc55cSDimitry Andric auto *InitSection = G.findSectionByName(InitSectionName); 719*349cc55cSDimitry Andric if (!InitSection) 720*349cc55cSDimitry Andric continue; 721*349cc55cSDimitry Andric 722*349cc55cSDimitry Andric // Make a pass over live symbols in the section: those blocks are already 723*349cc55cSDimitry Andric // preserved. 724*349cc55cSDimitry Andric DenseSet<jitlink::Block *> AlreadyLiveBlocks; 725*349cc55cSDimitry Andric for (auto &Sym : InitSection->symbols()) { 726*349cc55cSDimitry Andric auto &B = Sym->getBlock(); 727*349cc55cSDimitry Andric if (Sym->isLive() && Sym->getOffset() == 0 && 728*349cc55cSDimitry Andric Sym->getSize() == B.getSize() && !AlreadyLiveBlocks.count(&B)) { 729*349cc55cSDimitry Andric InitSectionSymbols.insert(Sym); 730*349cc55cSDimitry Andric AlreadyLiveBlocks.insert(&B); 731*349cc55cSDimitry Andric } 732*349cc55cSDimitry Andric } 733*349cc55cSDimitry Andric 734*349cc55cSDimitry Andric // Add anonymous symbols to preserve any not-already-preserved blocks. 735*349cc55cSDimitry Andric for (auto *B : InitSection->blocks()) 736*349cc55cSDimitry Andric if (!AlreadyLiveBlocks.count(B)) 737*349cc55cSDimitry Andric InitSectionSymbols.insert( 738*349cc55cSDimitry Andric &G.addAnonymousSymbol(*B, 0, B->getSize(), false, true)); 739*349cc55cSDimitry Andric } 740*349cc55cSDimitry Andric 741*349cc55cSDimitry Andric if (!InitSectionSymbols.empty()) { 742*349cc55cSDimitry Andric std::lock_guard<std::mutex> Lock(PluginMutex); 743*349cc55cSDimitry Andric InitSymbolDeps[&MR] = std::move(InitSectionSymbols); 744*349cc55cSDimitry Andric } 745*349cc55cSDimitry Andric 746*349cc55cSDimitry Andric return Error::success(); 747*349cc55cSDimitry Andric } 748*349cc55cSDimitry Andric 749*349cc55cSDimitry Andric Error ELFNixPlatform::ELFNixPlatformPlugin::registerInitSections( 750*349cc55cSDimitry Andric jitlink::LinkGraph &G, JITDylib &JD) { 751*349cc55cSDimitry Andric 752*349cc55cSDimitry Andric SmallVector<jitlink::Section *> InitSections; 753*349cc55cSDimitry Andric 754*349cc55cSDimitry Andric LLVM_DEBUG({ dbgs() << "ELFNixPlatform::registerInitSections\n"; }); 755*349cc55cSDimitry Andric 756*349cc55cSDimitry Andric for (auto InitSectionName : InitSectionNames) { 757*349cc55cSDimitry Andric if (auto *Sec = G.findSectionByName(InitSectionName)) { 758*349cc55cSDimitry Andric InitSections.push_back(Sec); 759*349cc55cSDimitry Andric } 760*349cc55cSDimitry Andric } 761*349cc55cSDimitry Andric 762*349cc55cSDimitry Andric // Dump the scraped inits. 763*349cc55cSDimitry Andric LLVM_DEBUG({ 764*349cc55cSDimitry Andric dbgs() << "ELFNixPlatform: Scraped " << G.getName() << " init sections:\n"; 765*349cc55cSDimitry Andric for (auto *Sec : InitSections) { 766*349cc55cSDimitry Andric jitlink::SectionRange R(*Sec); 767*349cc55cSDimitry Andric dbgs() << " " << Sec->getName() << ": " 768*349cc55cSDimitry Andric << formatv("[ {0:x} -- {1:x} ]", R.getStart(), R.getEnd()) << "\n"; 769*349cc55cSDimitry Andric } 770*349cc55cSDimitry Andric }); 771*349cc55cSDimitry Andric 772*349cc55cSDimitry Andric return MP.registerInitInfo(JD, InitSections); 773*349cc55cSDimitry Andric } 774*349cc55cSDimitry Andric 775*349cc55cSDimitry Andric Error ELFNixPlatform::ELFNixPlatformPlugin::fixTLVSectionsAndEdges( 776*349cc55cSDimitry Andric jitlink::LinkGraph &G, JITDylib &JD) { 777*349cc55cSDimitry Andric 778*349cc55cSDimitry Andric // TODO implement TLV support 779*349cc55cSDimitry Andric for (auto *Sym : G.external_symbols()) 780*349cc55cSDimitry Andric if (Sym->getName() == "__tls_get_addr") { 781*349cc55cSDimitry Andric Sym->setName("___orc_rt_elfnix_tls_get_addr"); 782*349cc55cSDimitry Andric } 783*349cc55cSDimitry Andric 784*349cc55cSDimitry Andric auto *TLSInfoEntrySection = G.findSectionByName("$__TLSINFO"); 785*349cc55cSDimitry Andric 786*349cc55cSDimitry Andric if (TLSInfoEntrySection) { 787*349cc55cSDimitry Andric Optional<uint64_t> Key; 788*349cc55cSDimitry Andric { 789*349cc55cSDimitry Andric std::lock_guard<std::mutex> Lock(MP.PlatformMutex); 790*349cc55cSDimitry Andric auto I = MP.JITDylibToPThreadKey.find(&JD); 791*349cc55cSDimitry Andric if (I != MP.JITDylibToPThreadKey.end()) 792*349cc55cSDimitry Andric Key = I->second; 793*349cc55cSDimitry Andric } 794*349cc55cSDimitry Andric if (!Key) { 795*349cc55cSDimitry Andric if (auto KeyOrErr = MP.createPThreadKey()) 796*349cc55cSDimitry Andric Key = *KeyOrErr; 797*349cc55cSDimitry Andric else 798*349cc55cSDimitry Andric return KeyOrErr.takeError(); 799*349cc55cSDimitry Andric } 800*349cc55cSDimitry Andric 801*349cc55cSDimitry Andric uint64_t PlatformKeyBits = 802*349cc55cSDimitry Andric support::endian::byte_swap(*Key, G.getEndianness()); 803*349cc55cSDimitry Andric 804*349cc55cSDimitry Andric for (auto *B : TLSInfoEntrySection->blocks()) { 805*349cc55cSDimitry Andric // FIXME: The TLS descriptor byte length may different with different 806*349cc55cSDimitry Andric // ISA 807*349cc55cSDimitry Andric assert(B->getSize() == (G.getPointerSize() * 2) && 808*349cc55cSDimitry Andric "TLS descriptor must be 2 words length"); 809*349cc55cSDimitry Andric auto TLSInfoEntryContent = B->getMutableContent(G); 810*349cc55cSDimitry Andric memcpy(TLSInfoEntryContent.data(), &PlatformKeyBits, G.getPointerSize()); 811*349cc55cSDimitry Andric } 812*349cc55cSDimitry Andric } 813*349cc55cSDimitry Andric 814*349cc55cSDimitry Andric return Error::success(); 815*349cc55cSDimitry Andric } 816*349cc55cSDimitry Andric 817*349cc55cSDimitry Andric } // End namespace orc. 818*349cc55cSDimitry Andric } // End namespace llvm. 819