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