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