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