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