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