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