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