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