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