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