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