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