1 //===------- ObjectLinkingLayer.cpp - JITLink backed ORC ObjectLayer ------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h" 10 #include "llvm/ExecutionEngine/JITLink/EHFrameSupport.h" 11 #include "llvm/ExecutionEngine/Orc/DebugObjectManagerPlugin.h" 12 #include "llvm/ExecutionEngine/Orc/ObjectFileInterface.h" 13 #include "llvm/ExecutionEngine/Orc/Shared/ObjectFormats.h" 14 #include "llvm/Support/MemoryBuffer.h" 15 #include <string> 16 #include <vector> 17 18 #define DEBUG_TYPE "orc" 19 20 using namespace llvm; 21 using namespace llvm::jitlink; 22 using namespace llvm::orc; 23 24 namespace { 25 26 bool hasInitializerSection(jitlink::LinkGraph &G) { 27 bool IsMachO = G.getTargetTriple().isOSBinFormatMachO(); 28 bool IsElf = G.getTargetTriple().isOSBinFormatELF(); 29 if (!IsMachO && !IsElf) 30 return false; 31 32 for (auto &Sec : G.sections()) { 33 if (IsMachO && isMachOInitializerSection(Sec.getName())) 34 return true; 35 if (IsElf && isELFInitializerSection(Sec.getName())) 36 return true; 37 } 38 39 return false; 40 } 41 42 JITTargetAddress getJITSymbolPtrForSymbol(Symbol &Sym) { 43 return Sym.getAddress().getValue(); 44 } 45 46 JITSymbolFlags getJITSymbolFlagsForSymbol(Symbol &Sym) { 47 JITSymbolFlags Flags; 48 49 if (Sym.getLinkage() == Linkage::Weak) 50 Flags |= JITSymbolFlags::Weak; 51 52 if (Sym.getScope() == Scope::Default) 53 Flags |= JITSymbolFlags::Exported; 54 55 if (Sym.isCallable()) 56 Flags |= JITSymbolFlags::Callable; 57 58 return Flags; 59 } 60 61 class LinkGraphMaterializationUnit : public MaterializationUnit { 62 public: 63 static std::unique_ptr<LinkGraphMaterializationUnit> 64 Create(ObjectLinkingLayer &ObjLinkingLayer, std::unique_ptr<LinkGraph> G) { 65 auto LGI = scanLinkGraph(ObjLinkingLayer.getExecutionSession(), *G); 66 return std::unique_ptr<LinkGraphMaterializationUnit>( 67 new LinkGraphMaterializationUnit(ObjLinkingLayer, std::move(G), 68 std::move(LGI))); 69 } 70 71 StringRef getName() const override { return G->getName(); } 72 void materialize(std::unique_ptr<MaterializationResponsibility> MR) override { 73 ObjLinkingLayer.emit(std::move(MR), std::move(G)); 74 } 75 76 private: 77 static Interface scanLinkGraph(ExecutionSession &ES, LinkGraph &G) { 78 79 Interface LGI; 80 81 for (auto *Sym : G.defined_symbols()) { 82 // Skip local symbols. 83 if (Sym->getScope() == Scope::Local) 84 continue; 85 assert(Sym->hasName() && "Anonymous non-local symbol?"); 86 87 LGI.SymbolFlags[ES.intern(Sym->getName())] = 88 getJITSymbolFlagsForSymbol(*Sym); 89 } 90 91 if (hasInitializerSection(G)) 92 LGI.InitSymbol = makeInitSymbol(ES, G); 93 94 return LGI; 95 } 96 97 static SymbolStringPtr makeInitSymbol(ExecutionSession &ES, LinkGraph &G) { 98 std::string InitSymString; 99 raw_string_ostream(InitSymString) 100 << "$." << G.getName() << ".__inits" << Counter++; 101 return ES.intern(InitSymString); 102 } 103 104 LinkGraphMaterializationUnit(ObjectLinkingLayer &ObjLinkingLayer, 105 std::unique_ptr<LinkGraph> G, Interface LGI) 106 : MaterializationUnit(std::move(LGI)), ObjLinkingLayer(ObjLinkingLayer), 107 G(std::move(G)) {} 108 109 void discard(const JITDylib &JD, const SymbolStringPtr &Name) override { 110 for (auto *Sym : G->defined_symbols()) 111 if (Sym->getName() == *Name) { 112 assert(Sym->getLinkage() == Linkage::Weak && 113 "Discarding non-weak definition"); 114 G->makeExternal(*Sym); 115 break; 116 } 117 } 118 119 ObjectLinkingLayer &ObjLinkingLayer; 120 std::unique_ptr<LinkGraph> G; 121 static std::atomic<uint64_t> Counter; 122 }; 123 124 std::atomic<uint64_t> LinkGraphMaterializationUnit::Counter{0}; 125 126 } // end anonymous namespace 127 128 namespace llvm { 129 namespace orc { 130 131 class ObjectLinkingLayerJITLinkContext final : public JITLinkContext { 132 public: 133 ObjectLinkingLayerJITLinkContext( 134 ObjectLinkingLayer &Layer, 135 std::unique_ptr<MaterializationResponsibility> MR, 136 std::unique_ptr<MemoryBuffer> ObjBuffer) 137 : JITLinkContext(&MR->getTargetJITDylib()), Layer(Layer), 138 MR(std::move(MR)), ObjBuffer(std::move(ObjBuffer)) {} 139 140 ~ObjectLinkingLayerJITLinkContext() { 141 // If there is an object buffer return function then use it to 142 // return ownership of the buffer. 143 if (Layer.ReturnObjectBuffer && ObjBuffer) 144 Layer.ReturnObjectBuffer(std::move(ObjBuffer)); 145 } 146 147 JITLinkMemoryManager &getMemoryManager() override { return Layer.MemMgr; } 148 149 void notifyMaterializing(LinkGraph &G) { 150 for (auto &P : Layer.Plugins) 151 P->notifyMaterializing(*MR, G, *this, 152 ObjBuffer ? ObjBuffer->getMemBufferRef() 153 : MemoryBufferRef()); 154 } 155 156 void notifyFailed(Error Err) override { 157 for (auto &P : Layer.Plugins) 158 Err = joinErrors(std::move(Err), P->notifyFailed(*MR)); 159 Layer.getExecutionSession().reportError(std::move(Err)); 160 MR->failMaterialization(); 161 } 162 163 void lookup(const LookupMap &Symbols, 164 std::unique_ptr<JITLinkAsyncLookupContinuation> LC) override { 165 166 JITDylibSearchOrder LinkOrder; 167 MR->getTargetJITDylib().withLinkOrderDo( 168 [&](const JITDylibSearchOrder &LO) { LinkOrder = LO; }); 169 170 auto &ES = Layer.getExecutionSession(); 171 172 SymbolLookupSet LookupSet; 173 for (auto &KV : Symbols) { 174 orc::SymbolLookupFlags LookupFlags; 175 switch (KV.second) { 176 case jitlink::SymbolLookupFlags::RequiredSymbol: 177 LookupFlags = orc::SymbolLookupFlags::RequiredSymbol; 178 break; 179 case jitlink::SymbolLookupFlags::WeaklyReferencedSymbol: 180 LookupFlags = orc::SymbolLookupFlags::WeaklyReferencedSymbol; 181 break; 182 } 183 LookupSet.add(ES.intern(KV.first), LookupFlags); 184 } 185 186 // OnResolve -- De-intern the symbols and pass the result to the linker. 187 auto OnResolve = [LookupContinuation = 188 std::move(LC)](Expected<SymbolMap> Result) mutable { 189 if (!Result) 190 LookupContinuation->run(Result.takeError()); 191 else { 192 AsyncLookupResult LR; 193 for (auto &KV : *Result) 194 LR[*KV.first] = KV.second; 195 LookupContinuation->run(std::move(LR)); 196 } 197 }; 198 199 for (auto &KV : InternalNamedSymbolDeps) { 200 SymbolDependenceMap InternalDeps; 201 InternalDeps[&MR->getTargetJITDylib()] = std::move(KV.second); 202 MR->addDependencies(KV.first, InternalDeps); 203 } 204 205 ES.lookup(LookupKind::Static, LinkOrder, std::move(LookupSet), 206 SymbolState::Resolved, std::move(OnResolve), 207 [this](const SymbolDependenceMap &Deps) { 208 registerDependencies(Deps); 209 }); 210 } 211 212 Error notifyResolved(LinkGraph &G) override { 213 auto &ES = Layer.getExecutionSession(); 214 215 SymbolFlagsMap ExtraSymbolsToClaim; 216 bool AutoClaim = Layer.AutoClaimObjectSymbols; 217 218 SymbolMap InternedResult; 219 for (auto *Sym : G.defined_symbols()) 220 if (Sym->hasName() && Sym->getScope() != Scope::Local) { 221 auto InternedName = ES.intern(Sym->getName()); 222 auto Ptr = getJITSymbolPtrForSymbol(*Sym); 223 auto Flags = getJITSymbolFlagsForSymbol(*Sym); 224 InternedResult[InternedName] = JITEvaluatedSymbol(Ptr, Flags); 225 if (AutoClaim && !MR->getSymbols().count(InternedName)) { 226 assert(!ExtraSymbolsToClaim.count(InternedName) && 227 "Duplicate symbol to claim?"); 228 ExtraSymbolsToClaim[InternedName] = Flags; 229 } 230 } 231 232 for (auto *Sym : G.absolute_symbols()) 233 if (Sym->hasName() && Sym->getScope() != Scope::Local) { 234 auto InternedName = ES.intern(Sym->getName()); 235 auto Ptr = getJITSymbolPtrForSymbol(*Sym); 236 auto Flags = getJITSymbolFlagsForSymbol(*Sym); 237 InternedResult[InternedName] = JITEvaluatedSymbol(Ptr, Flags); 238 if (AutoClaim && !MR->getSymbols().count(InternedName)) { 239 assert(!ExtraSymbolsToClaim.count(InternedName) && 240 "Duplicate symbol to claim?"); 241 ExtraSymbolsToClaim[InternedName] = Flags; 242 } 243 } 244 245 if (!ExtraSymbolsToClaim.empty()) 246 if (auto Err = MR->defineMaterializing(ExtraSymbolsToClaim)) 247 return Err; 248 249 { 250 251 // Check that InternedResult matches up with MR->getSymbols(), overriding 252 // flags if requested. 253 // This guards against faulty transformations / compilers / object caches. 254 255 // First check that there aren't any missing symbols. 256 size_t NumMaterializationSideEffectsOnlySymbols = 0; 257 SymbolNameVector ExtraSymbols; 258 SymbolNameVector MissingSymbols; 259 for (auto &KV : MR->getSymbols()) { 260 261 auto I = InternedResult.find(KV.first); 262 263 // If this is a materialization-side-effects only symbol then bump 264 // the counter and make sure it's *not* defined, otherwise make 265 // sure that it is defined. 266 if (KV.second.hasMaterializationSideEffectsOnly()) { 267 ++NumMaterializationSideEffectsOnlySymbols; 268 if (I != InternedResult.end()) 269 ExtraSymbols.push_back(KV.first); 270 continue; 271 } else if (I == InternedResult.end()) 272 MissingSymbols.push_back(KV.first); 273 else if (Layer.OverrideObjectFlags) 274 I->second.setFlags(KV.second); 275 } 276 277 // If there were missing symbols then report the error. 278 if (!MissingSymbols.empty()) 279 return make_error<MissingSymbolDefinitions>( 280 Layer.getExecutionSession().getSymbolStringPool(), G.getName(), 281 std::move(MissingSymbols)); 282 283 // If there are more definitions than expected, add them to the 284 // ExtraSymbols vector. 285 if (InternedResult.size() > 286 MR->getSymbols().size() - NumMaterializationSideEffectsOnlySymbols) { 287 for (auto &KV : InternedResult) 288 if (!MR->getSymbols().count(KV.first)) 289 ExtraSymbols.push_back(KV.first); 290 } 291 292 // If there were extra definitions then report the error. 293 if (!ExtraSymbols.empty()) 294 return make_error<UnexpectedSymbolDefinitions>( 295 Layer.getExecutionSession().getSymbolStringPool(), G.getName(), 296 std::move(ExtraSymbols)); 297 } 298 299 if (auto Err = MR->notifyResolved(InternedResult)) 300 return Err; 301 302 Layer.notifyLoaded(*MR); 303 return Error::success(); 304 } 305 306 void notifyFinalized(JITLinkMemoryManager::FinalizedAlloc A) override { 307 if (auto Err = Layer.notifyEmitted(*MR, std::move(A))) { 308 Layer.getExecutionSession().reportError(std::move(Err)); 309 MR->failMaterialization(); 310 return; 311 } 312 if (auto Err = MR->notifyEmitted()) { 313 Layer.getExecutionSession().reportError(std::move(Err)); 314 MR->failMaterialization(); 315 } 316 } 317 318 LinkGraphPassFunction getMarkLivePass(const Triple &TT) const override { 319 return [this](LinkGraph &G) { return markResponsibilitySymbolsLive(G); }; 320 } 321 322 Error modifyPassConfig(LinkGraph &LG, PassConfiguration &Config) override { 323 // Add passes to mark duplicate defs as should-discard, and to walk the 324 // link graph to build the symbol dependence graph. 325 Config.PrePrunePasses.push_back([this](LinkGraph &G) { 326 return claimOrExternalizeWeakAndCommonSymbols(G); 327 }); 328 329 Layer.modifyPassConfig(*MR, LG, Config); 330 331 Config.PostPrunePasses.push_back( 332 [this](LinkGraph &G) { return computeNamedSymbolDependencies(G); }); 333 334 return Error::success(); 335 } 336 337 private: 338 // Symbol name dependencies: 339 // Internal: Defined in this graph. 340 // External: Defined externally. 341 struct BlockSymbolDependencies { 342 SymbolNameSet Internal, External; 343 }; 344 345 // Lazily populated map of blocks to BlockSymbolDependencies values. 346 class BlockDependenciesMap { 347 public: 348 BlockDependenciesMap(ExecutionSession &ES, 349 DenseMap<const Block *, DenseSet<Block *>> BlockDeps) 350 : ES(ES), BlockDeps(std::move(BlockDeps)) {} 351 352 const BlockSymbolDependencies &operator[](const Block &B) { 353 // Check the cache first. 354 auto I = BlockTransitiveDepsCache.find(&B); 355 if (I != BlockTransitiveDepsCache.end()) 356 return I->second; 357 358 // No value. Populate the cache. 359 BlockSymbolDependencies BTDCacheVal; 360 auto BDI = BlockDeps.find(&B); 361 assert(BDI != BlockDeps.end() && "No block dependencies"); 362 363 for (auto *BDep : BDI->second) { 364 auto &BID = getBlockImmediateDeps(*BDep); 365 for (auto &ExternalDep : BID.External) 366 BTDCacheVal.External.insert(ExternalDep); 367 for (auto &InternalDep : BID.Internal) 368 BTDCacheVal.Internal.insert(InternalDep); 369 } 370 371 return BlockTransitiveDepsCache 372 .insert(std::make_pair(&B, std::move(BTDCacheVal))) 373 .first->second; 374 } 375 376 SymbolStringPtr &getInternedName(Symbol &Sym) { 377 auto I = NameCache.find(&Sym); 378 if (I != NameCache.end()) 379 return I->second; 380 381 return NameCache.insert(std::make_pair(&Sym, ES.intern(Sym.getName()))) 382 .first->second; 383 } 384 385 private: 386 BlockSymbolDependencies &getBlockImmediateDeps(Block &B) { 387 // Check the cache first. 388 auto I = BlockImmediateDepsCache.find(&B); 389 if (I != BlockImmediateDepsCache.end()) 390 return I->second; 391 392 BlockSymbolDependencies BIDCacheVal; 393 for (auto &E : B.edges()) { 394 auto &Tgt = E.getTarget(); 395 if (Tgt.getScope() != Scope::Local) { 396 if (Tgt.isExternal()) 397 BIDCacheVal.External.insert(getInternedName(Tgt)); 398 else 399 BIDCacheVal.Internal.insert(getInternedName(Tgt)); 400 } 401 } 402 403 return BlockImmediateDepsCache 404 .insert(std::make_pair(&B, std::move(BIDCacheVal))) 405 .first->second; 406 } 407 408 ExecutionSession &ES; 409 DenseMap<const Block *, DenseSet<Block *>> BlockDeps; 410 DenseMap<const Symbol *, SymbolStringPtr> NameCache; 411 DenseMap<const Block *, BlockSymbolDependencies> BlockImmediateDepsCache; 412 DenseMap<const Block *, BlockSymbolDependencies> BlockTransitiveDepsCache; 413 }; 414 415 Error claimOrExternalizeWeakAndCommonSymbols(LinkGraph &G) { 416 auto &ES = Layer.getExecutionSession(); 417 418 SymbolFlagsMap NewSymbolsToClaim; 419 std::vector<std::pair<SymbolStringPtr, Symbol *>> NameToSym; 420 421 auto ProcessSymbol = [&](Symbol *Sym) { 422 if (Sym->hasName() && Sym->getLinkage() == Linkage::Weak && 423 Sym->getScope() != Scope::Local) { 424 auto Name = ES.intern(Sym->getName()); 425 if (!MR->getSymbols().count(ES.intern(Sym->getName()))) { 426 NewSymbolsToClaim[Name] = 427 getJITSymbolFlagsForSymbol(*Sym) | JITSymbolFlags::Weak; 428 NameToSym.push_back(std::make_pair(std::move(Name), Sym)); 429 } 430 } 431 }; 432 433 for (auto *Sym : G.defined_symbols()) 434 ProcessSymbol(Sym); 435 for (auto *Sym : G.absolute_symbols()) 436 ProcessSymbol(Sym); 437 438 // Attempt to claim all weak defs that we're not already responsible for. 439 // This cannot fail -- any clashes will just result in rejection of our 440 // claim, at which point we'll externalize that symbol. 441 cantFail(MR->defineMaterializing(std::move(NewSymbolsToClaim))); 442 443 // Walk the list of symbols that we just tried to claim. Symbols that we're 444 // responsible for are marked live. Symbols that we're not responsible for 445 // are turned into external references. 446 for (auto &KV : NameToSym) { 447 if (MR->getSymbols().count(KV.first)) 448 KV.second->setLive(true); 449 else 450 G.makeExternal(*KV.second); 451 } 452 453 return Error::success(); 454 } 455 456 Error markResponsibilitySymbolsLive(LinkGraph &G) const { 457 auto &ES = Layer.getExecutionSession(); 458 for (auto *Sym : G.defined_symbols()) 459 if (Sym->hasName() && MR->getSymbols().count(ES.intern(Sym->getName()))) 460 Sym->setLive(true); 461 return Error::success(); 462 } 463 464 Error computeNamedSymbolDependencies(LinkGraph &G) { 465 auto &ES = MR->getTargetJITDylib().getExecutionSession(); 466 auto BlockDeps = computeBlockNonLocalDeps(G); 467 468 // Compute dependencies for symbols defined in the JITLink graph. 469 for (auto *Sym : G.defined_symbols()) { 470 471 // Skip local symbols: we do not track dependencies for these. 472 if (Sym->getScope() == Scope::Local) 473 continue; 474 assert(Sym->hasName() && 475 "Defined non-local jitlink::Symbol should have a name"); 476 477 auto &SymDeps = BlockDeps[Sym->getBlock()]; 478 if (SymDeps.External.empty() && SymDeps.Internal.empty()) 479 continue; 480 481 auto SymName = ES.intern(Sym->getName()); 482 if (!SymDeps.External.empty()) 483 ExternalNamedSymbolDeps[SymName] = SymDeps.External; 484 if (!SymDeps.Internal.empty()) 485 InternalNamedSymbolDeps[SymName] = SymDeps.Internal; 486 } 487 488 for (auto &P : Layer.Plugins) { 489 auto SynthDeps = P->getSyntheticSymbolDependencies(*MR); 490 if (SynthDeps.empty()) 491 continue; 492 493 DenseSet<Block *> BlockVisited; 494 for (auto &KV : SynthDeps) { 495 auto &Name = KV.first; 496 auto &DepsForName = KV.second; 497 for (auto *Sym : DepsForName) { 498 if (Sym->getScope() == Scope::Local) { 499 auto &BDeps = BlockDeps[Sym->getBlock()]; 500 for (auto &S : BDeps.Internal) 501 InternalNamedSymbolDeps[Name].insert(S); 502 for (auto &S : BDeps.External) 503 ExternalNamedSymbolDeps[Name].insert(S); 504 } else { 505 if (Sym->isExternal()) 506 ExternalNamedSymbolDeps[Name].insert( 507 BlockDeps.getInternedName(*Sym)); 508 else 509 InternalNamedSymbolDeps[Name].insert( 510 BlockDeps.getInternedName(*Sym)); 511 } 512 } 513 } 514 } 515 516 return Error::success(); 517 } 518 519 BlockDependenciesMap computeBlockNonLocalDeps(LinkGraph &G) { 520 // First calculate the reachable-via-non-local-symbol blocks for each block. 521 struct BlockInfo { 522 DenseSet<Block *> Dependencies; 523 DenseSet<Block *> Dependants; 524 bool DependenciesChanged = true; 525 }; 526 DenseMap<Block *, BlockInfo> BlockInfos; 527 SmallVector<Block *> WorkList; 528 529 // Pre-allocate map entries. This prevents any iterator/reference 530 // invalidation in the next loop. 531 for (auto *B : G.blocks()) 532 (void)BlockInfos[B]; 533 534 // Build initial worklist, record block dependencies/dependants and 535 // non-local symbol dependencies. 536 for (auto *B : G.blocks()) { 537 auto &BI = BlockInfos[B]; 538 for (auto &E : B->edges()) { 539 if (E.getTarget().getScope() == Scope::Local && 540 !E.getTarget().isAbsolute()) { 541 auto &TgtB = E.getTarget().getBlock(); 542 if (&TgtB != B) { 543 BI.Dependencies.insert(&TgtB); 544 BlockInfos[&TgtB].Dependants.insert(B); 545 } 546 } 547 } 548 549 // If this node has both dependants and dependencies then add it to the 550 // worklist to propagate the dependencies to the dependants. 551 if (!BI.Dependants.empty() && !BI.Dependencies.empty()) 552 WorkList.push_back(B); 553 } 554 555 // Propagate block-level dependencies through the block-dependence graph. 556 while (!WorkList.empty()) { 557 auto *B = WorkList.pop_back_val(); 558 559 auto &BI = BlockInfos[B]; 560 assert(BI.DependenciesChanged && 561 "Block in worklist has unchanged dependencies"); 562 BI.DependenciesChanged = false; 563 for (auto *Dependant : BI.Dependants) { 564 auto &DependantBI = BlockInfos[Dependant]; 565 for (auto *Dependency : BI.Dependencies) { 566 if (Dependant != Dependency && 567 DependantBI.Dependencies.insert(Dependency).second) 568 if (!DependantBI.DependenciesChanged) { 569 DependantBI.DependenciesChanged = true; 570 WorkList.push_back(Dependant); 571 } 572 } 573 } 574 } 575 576 DenseMap<const Block *, DenseSet<Block *>> BlockDeps; 577 for (auto &KV : BlockInfos) 578 BlockDeps[KV.first] = std::move(KV.second.Dependencies); 579 580 return BlockDependenciesMap(Layer.getExecutionSession(), 581 std::move(BlockDeps)); 582 } 583 584 void registerDependencies(const SymbolDependenceMap &QueryDeps) { 585 for (auto &NamedDepsEntry : ExternalNamedSymbolDeps) { 586 auto &Name = NamedDepsEntry.first; 587 auto &NameDeps = NamedDepsEntry.second; 588 SymbolDependenceMap SymbolDeps; 589 590 for (const auto &QueryDepsEntry : QueryDeps) { 591 JITDylib &SourceJD = *QueryDepsEntry.first; 592 const SymbolNameSet &Symbols = QueryDepsEntry.second; 593 auto &DepsForJD = SymbolDeps[&SourceJD]; 594 595 for (const auto &S : Symbols) 596 if (NameDeps.count(S)) 597 DepsForJD.insert(S); 598 599 if (DepsForJD.empty()) 600 SymbolDeps.erase(&SourceJD); 601 } 602 603 MR->addDependencies(Name, SymbolDeps); 604 } 605 } 606 607 ObjectLinkingLayer &Layer; 608 std::unique_ptr<MaterializationResponsibility> MR; 609 std::unique_ptr<MemoryBuffer> ObjBuffer; 610 DenseMap<SymbolStringPtr, SymbolNameSet> ExternalNamedSymbolDeps; 611 DenseMap<SymbolStringPtr, SymbolNameSet> InternalNamedSymbolDeps; 612 }; 613 614 ObjectLinkingLayer::Plugin::~Plugin() = default; 615 616 char ObjectLinkingLayer::ID; 617 618 using BaseT = RTTIExtends<ObjectLinkingLayer, ObjectLayer>; 619 620 ObjectLinkingLayer::ObjectLinkingLayer(ExecutionSession &ES) 621 : BaseT(ES), MemMgr(ES.getExecutorProcessControl().getMemMgr()) { 622 ES.registerResourceManager(*this); 623 } 624 625 ObjectLinkingLayer::ObjectLinkingLayer(ExecutionSession &ES, 626 JITLinkMemoryManager &MemMgr) 627 : BaseT(ES), MemMgr(MemMgr) { 628 ES.registerResourceManager(*this); 629 } 630 631 ObjectLinkingLayer::ObjectLinkingLayer( 632 ExecutionSession &ES, std::unique_ptr<JITLinkMemoryManager> MemMgr) 633 : BaseT(ES), MemMgr(*MemMgr), MemMgrOwnership(std::move(MemMgr)) { 634 ES.registerResourceManager(*this); 635 } 636 637 ObjectLinkingLayer::~ObjectLinkingLayer() { 638 assert(Allocs.empty() && "Layer destroyed with resources still attached"); 639 getExecutionSession().deregisterResourceManager(*this); 640 } 641 642 Error ObjectLinkingLayer::add(ResourceTrackerSP RT, 643 std::unique_ptr<LinkGraph> G) { 644 auto &JD = RT->getJITDylib(); 645 return JD.define(LinkGraphMaterializationUnit::Create(*this, std::move(G)), 646 std::move(RT)); 647 } 648 649 void ObjectLinkingLayer::emit(std::unique_ptr<MaterializationResponsibility> R, 650 std::unique_ptr<MemoryBuffer> O) { 651 assert(O && "Object must not be null"); 652 MemoryBufferRef ObjBuffer = O->getMemBufferRef(); 653 654 auto Ctx = std::make_unique<ObjectLinkingLayerJITLinkContext>( 655 *this, std::move(R), std::move(O)); 656 if (auto G = createLinkGraphFromObject(ObjBuffer)) { 657 Ctx->notifyMaterializing(**G); 658 link(std::move(*G), std::move(Ctx)); 659 } else { 660 Ctx->notifyFailed(G.takeError()); 661 } 662 } 663 664 void ObjectLinkingLayer::emit(std::unique_ptr<MaterializationResponsibility> R, 665 std::unique_ptr<LinkGraph> G) { 666 auto Ctx = std::make_unique<ObjectLinkingLayerJITLinkContext>( 667 *this, std::move(R), nullptr); 668 Ctx->notifyMaterializing(*G); 669 link(std::move(G), std::move(Ctx)); 670 } 671 672 void ObjectLinkingLayer::modifyPassConfig(MaterializationResponsibility &MR, 673 LinkGraph &G, 674 PassConfiguration &PassConfig) { 675 for (auto &P : Plugins) 676 P->modifyPassConfig(MR, G, PassConfig); 677 } 678 679 void ObjectLinkingLayer::notifyLoaded(MaterializationResponsibility &MR) { 680 for (auto &P : Plugins) 681 P->notifyLoaded(MR); 682 } 683 684 Error ObjectLinkingLayer::notifyEmitted(MaterializationResponsibility &MR, 685 FinalizedAlloc FA) { 686 Error Err = Error::success(); 687 for (auto &P : Plugins) 688 Err = joinErrors(std::move(Err), P->notifyEmitted(MR)); 689 690 if (Err) 691 return Err; 692 693 return MR.withResourceKeyDo( 694 [&](ResourceKey K) { Allocs[K].push_back(std::move(FA)); }); 695 } 696 697 Error ObjectLinkingLayer::handleRemoveResources(JITDylib &JD, ResourceKey K) { 698 699 { 700 Error Err = Error::success(); 701 for (auto &P : Plugins) 702 Err = joinErrors(std::move(Err), P->notifyRemovingResources(JD, K)); 703 if (Err) 704 return Err; 705 } 706 707 std::vector<FinalizedAlloc> AllocsToRemove; 708 getExecutionSession().runSessionLocked([&] { 709 auto I = Allocs.find(K); 710 if (I != Allocs.end()) { 711 std::swap(AllocsToRemove, I->second); 712 Allocs.erase(I); 713 } 714 }); 715 716 if (AllocsToRemove.empty()) 717 return Error::success(); 718 719 return MemMgr.deallocate(std::move(AllocsToRemove)); 720 } 721 722 void ObjectLinkingLayer::handleTransferResources(JITDylib &JD, 723 ResourceKey DstKey, 724 ResourceKey SrcKey) { 725 auto I = Allocs.find(SrcKey); 726 if (I != Allocs.end()) { 727 auto &SrcAllocs = I->second; 728 auto &DstAllocs = Allocs[DstKey]; 729 DstAllocs.reserve(DstAllocs.size() + SrcAllocs.size()); 730 for (auto &Alloc : SrcAllocs) 731 DstAllocs.push_back(std::move(Alloc)); 732 733 // Erase SrcKey entry using value rather than iterator I: I may have been 734 // invalidated when we looked up DstKey. 735 Allocs.erase(SrcKey); 736 } 737 738 for (auto &P : Plugins) 739 P->notifyTransferringResources(JD, DstKey, SrcKey); 740 } 741 742 EHFrameRegistrationPlugin::EHFrameRegistrationPlugin( 743 ExecutionSession &ES, std::unique_ptr<EHFrameRegistrar> Registrar) 744 : ES(ES), Registrar(std::move(Registrar)) {} 745 746 void EHFrameRegistrationPlugin::modifyPassConfig( 747 MaterializationResponsibility &MR, LinkGraph &G, 748 PassConfiguration &PassConfig) { 749 750 PassConfig.PostFixupPasses.push_back(createEHFrameRecorderPass( 751 G.getTargetTriple(), [this, &MR](ExecutorAddr Addr, size_t Size) { 752 if (Addr) { 753 std::lock_guard<std::mutex> Lock(EHFramePluginMutex); 754 assert(!InProcessLinks.count(&MR) && 755 "Link for MR already being tracked?"); 756 InProcessLinks[&MR] = {Addr, Size}; 757 } 758 })); 759 } 760 761 Error EHFrameRegistrationPlugin::notifyEmitted( 762 MaterializationResponsibility &MR) { 763 764 ExecutorAddrRange EmittedRange; 765 { 766 std::lock_guard<std::mutex> Lock(EHFramePluginMutex); 767 768 auto EHFrameRangeItr = InProcessLinks.find(&MR); 769 if (EHFrameRangeItr == InProcessLinks.end()) 770 return Error::success(); 771 772 EmittedRange = EHFrameRangeItr->second; 773 assert(EmittedRange.Start && "eh-frame addr to register can not be null"); 774 InProcessLinks.erase(EHFrameRangeItr); 775 } 776 777 if (auto Err = MR.withResourceKeyDo( 778 [&](ResourceKey K) { EHFrameRanges[K].push_back(EmittedRange); })) 779 return Err; 780 781 return Registrar->registerEHFrames(EmittedRange); 782 } 783 784 Error EHFrameRegistrationPlugin::notifyFailed( 785 MaterializationResponsibility &MR) { 786 std::lock_guard<std::mutex> Lock(EHFramePluginMutex); 787 InProcessLinks.erase(&MR); 788 return Error::success(); 789 } 790 791 Error EHFrameRegistrationPlugin::notifyRemovingResources(JITDylib &JD, 792 ResourceKey K) { 793 std::vector<ExecutorAddrRange> RangesToRemove; 794 795 ES.runSessionLocked([&] { 796 auto I = EHFrameRanges.find(K); 797 if (I != EHFrameRanges.end()) { 798 RangesToRemove = std::move(I->second); 799 EHFrameRanges.erase(I); 800 } 801 }); 802 803 Error Err = Error::success(); 804 while (!RangesToRemove.empty()) { 805 auto RangeToRemove = RangesToRemove.back(); 806 RangesToRemove.pop_back(); 807 assert(RangeToRemove.Start && "Untracked eh-frame range must not be null"); 808 Err = joinErrors(std::move(Err), 809 Registrar->deregisterEHFrames(RangeToRemove)); 810 } 811 812 return Err; 813 } 814 815 void EHFrameRegistrationPlugin::notifyTransferringResources( 816 JITDylib &JD, ResourceKey DstKey, ResourceKey SrcKey) { 817 auto SI = EHFrameRanges.find(SrcKey); 818 if (SI == EHFrameRanges.end()) 819 return; 820 821 auto DI = EHFrameRanges.find(DstKey); 822 if (DI != EHFrameRanges.end()) { 823 auto &SrcRanges = SI->second; 824 auto &DstRanges = DI->second; 825 DstRanges.reserve(DstRanges.size() + SrcRanges.size()); 826 for (auto &SrcRange : SrcRanges) 827 DstRanges.push_back(std::move(SrcRange)); 828 EHFrameRanges.erase(SI); 829 } else { 830 // We need to move SrcKey's ranges over without invalidating the SI 831 // iterator. 832 auto Tmp = std::move(SI->second); 833 EHFrameRanges.erase(SI); 834 EHFrameRanges[DstKey] = std::move(Tmp); 835 } 836 } 837 838 } // End namespace orc. 839 } // End namespace llvm. 840