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