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/DebugUtils.h" 13 #include "llvm/ExecutionEngine/Orc/Shared/ObjectFormats.h" 14 #include "llvm/Support/MemoryBuffer.h" 15 16 #include <string> 17 18 #define DEBUG_TYPE "orc" 19 20 using namespace llvm; 21 using namespace llvm::jitlink; 22 using namespace llvm::orc; 23 24 namespace { 25 26 bool hasInitializerSection(jitlink::LinkGraph &G) { 27 bool IsMachO = G.getTargetTriple().isOSBinFormatMachO(); 28 bool IsElf = G.getTargetTriple().isOSBinFormatELF(); 29 if (!IsMachO && !IsElf) 30 return false; 31 32 for (auto &Sec : G.sections()) { 33 if (IsMachO && isMachOInitializerSection(Sec.getName())) 34 return true; 35 if (IsElf && isELFInitializerSection(Sec.getName())) 36 return true; 37 } 38 39 return false; 40 } 41 42 ExecutorAddr getJITSymbolPtrForSymbol(Symbol &Sym, const Triple &TT) { 43 switch (TT.getArch()) { 44 case Triple::arm: 45 case Triple::armeb: 46 case Triple::thumb: 47 case Triple::thumbeb: 48 if (hasTargetFlags(Sym, aarch32::ThumbSymbol)) { 49 // Set LSB to indicate thumb target 50 assert(Sym.isCallable() && "Only callable symbols can have thumb flag"); 51 assert((Sym.getAddress().getValue() & 0x01) == 0 && "LSB is clear"); 52 return Sym.getAddress() + 0x01; 53 } 54 return Sym.getAddress(); 55 default: 56 return Sym.getAddress(); 57 } 58 } 59 60 JITSymbolFlags getJITSymbolFlagsForSymbol(Symbol &Sym) { 61 JITSymbolFlags Flags; 62 63 if (Sym.getLinkage() == Linkage::Weak) 64 Flags |= JITSymbolFlags::Weak; 65 66 if (Sym.getScope() == Scope::Default) 67 Flags |= JITSymbolFlags::Exported; 68 else if (Sym.getScope() == Scope::SideEffectsOnly) 69 Flags |= JITSymbolFlags::MaterializationSideEffectsOnly; 70 71 if (Sym.isCallable()) 72 Flags |= JITSymbolFlags::Callable; 73 74 return Flags; 75 } 76 77 class LinkGraphMaterializationUnit : public MaterializationUnit { 78 public: 79 static std::unique_ptr<LinkGraphMaterializationUnit> 80 Create(ObjectLinkingLayer &ObjLinkingLayer, std::unique_ptr<LinkGraph> G) { 81 auto LGI = scanLinkGraph(ObjLinkingLayer.getExecutionSession(), *G); 82 return std::unique_ptr<LinkGraphMaterializationUnit>( 83 new LinkGraphMaterializationUnit(ObjLinkingLayer, std::move(G), 84 std::move(LGI))); 85 } 86 87 StringRef getName() const override { return G->getName(); } 88 void materialize(std::unique_ptr<MaterializationResponsibility> MR) override { 89 ObjLinkingLayer.emit(std::move(MR), std::move(G)); 90 } 91 92 private: 93 static Interface scanLinkGraph(ExecutionSession &ES, LinkGraph &G) { 94 95 Interface LGI; 96 97 auto AddSymbol = [&](Symbol *Sym) { 98 // Skip local symbols. 99 if (Sym->getScope() == Scope::Local) 100 return; 101 assert(Sym->hasName() && "Anonymous non-local symbol?"); 102 103 LGI.SymbolFlags[ES.intern(Sym->getName())] = 104 getJITSymbolFlagsForSymbol(*Sym); 105 }; 106 107 for (auto *Sym : G.defined_symbols()) 108 AddSymbol(Sym); 109 for (auto *Sym : G.absolute_symbols()) 110 AddSymbol(Sym); 111 112 if (hasInitializerSection(G)) 113 LGI.InitSymbol = makeInitSymbol(ES, G); 114 115 return LGI; 116 } 117 118 static SymbolStringPtr makeInitSymbol(ExecutionSession &ES, LinkGraph &G) { 119 std::string InitSymString; 120 raw_string_ostream(InitSymString) 121 << "$." << G.getName() << ".__inits" << Counter++; 122 return ES.intern(InitSymString); 123 } 124 125 LinkGraphMaterializationUnit(ObjectLinkingLayer &ObjLinkingLayer, 126 std::unique_ptr<LinkGraph> G, Interface LGI) 127 : MaterializationUnit(std::move(LGI)), ObjLinkingLayer(ObjLinkingLayer), 128 G(std::move(G)) {} 129 130 void discard(const JITDylib &JD, const SymbolStringPtr &Name) override { 131 for (auto *Sym : G->defined_symbols()) 132 if (Sym->getName() == *Name) { 133 assert(Sym->getLinkage() == Linkage::Weak && 134 "Discarding non-weak definition"); 135 G->makeExternal(*Sym); 136 break; 137 } 138 } 139 140 ObjectLinkingLayer &ObjLinkingLayer; 141 std::unique_ptr<LinkGraph> G; 142 static std::atomic<uint64_t> Counter; 143 }; 144 145 std::atomic<uint64_t> LinkGraphMaterializationUnit::Counter{0}; 146 147 } // end anonymous namespace 148 149 namespace llvm { 150 namespace orc { 151 152 class ObjectLinkingLayerJITLinkContext final : public JITLinkContext { 153 public: 154 ObjectLinkingLayerJITLinkContext( 155 ObjectLinkingLayer &Layer, 156 std::unique_ptr<MaterializationResponsibility> MR, 157 std::unique_ptr<MemoryBuffer> ObjBuffer) 158 : JITLinkContext(&MR->getTargetJITDylib()), Layer(Layer), 159 MR(std::move(MR)), ObjBuffer(std::move(ObjBuffer)) { 160 std::lock_guard<std::mutex> Lock(Layer.LayerMutex); 161 Plugins = Layer.Plugins; 162 } 163 164 ~ObjectLinkingLayerJITLinkContext() { 165 // If there is an object buffer return function then use it to 166 // return ownership of the buffer. 167 if (Layer.ReturnObjectBuffer && ObjBuffer) 168 Layer.ReturnObjectBuffer(std::move(ObjBuffer)); 169 } 170 171 JITLinkMemoryManager &getMemoryManager() override { return Layer.MemMgr; } 172 173 void notifyMaterializing(LinkGraph &G) { 174 for (auto &P : Plugins) 175 P->notifyMaterializing(*MR, G, *this, 176 ObjBuffer ? ObjBuffer->getMemBufferRef() 177 : MemoryBufferRef()); 178 } 179 180 void notifyFailed(Error Err) override { 181 for (auto &P : Plugins) 182 Err = joinErrors(std::move(Err), P->notifyFailed(*MR)); 183 Layer.getExecutionSession().reportError(std::move(Err)); 184 MR->failMaterialization(); 185 } 186 187 void lookup(const LookupMap &Symbols, 188 std::unique_ptr<JITLinkAsyncLookupContinuation> LC) override { 189 190 JITDylibSearchOrder LinkOrder; 191 MR->getTargetJITDylib().withLinkOrderDo( 192 [&](const JITDylibSearchOrder &LO) { LinkOrder = LO; }); 193 194 auto &ES = Layer.getExecutionSession(); 195 196 SymbolLookupSet LookupSet; 197 for (auto &KV : Symbols) { 198 orc::SymbolLookupFlags LookupFlags; 199 switch (KV.second) { 200 case jitlink::SymbolLookupFlags::RequiredSymbol: 201 LookupFlags = orc::SymbolLookupFlags::RequiredSymbol; 202 break; 203 case jitlink::SymbolLookupFlags::WeaklyReferencedSymbol: 204 LookupFlags = orc::SymbolLookupFlags::WeaklyReferencedSymbol; 205 break; 206 } 207 LookupSet.add(ES.intern(KV.first), LookupFlags); 208 } 209 210 // OnResolve -- De-intern the symbols and pass the result to the linker. 211 auto OnResolve = [LookupContinuation = 212 std::move(LC)](Expected<SymbolMap> Result) mutable { 213 if (!Result) 214 LookupContinuation->run(Result.takeError()); 215 else { 216 AsyncLookupResult LR; 217 for (auto &KV : *Result) 218 LR[*KV.first] = KV.second; 219 LookupContinuation->run(std::move(LR)); 220 } 221 }; 222 223 ES.lookup(LookupKind::Static, LinkOrder, std::move(LookupSet), 224 SymbolState::Resolved, std::move(OnResolve), 225 [this](const SymbolDependenceMap &Deps) { 226 // Translate LookupDeps map to SymbolSourceJD. 227 for (auto &[DepJD, Deps] : Deps) 228 for (auto &DepSym : Deps) 229 SymbolSourceJDs[NonOwningSymbolStringPtr(DepSym)] = DepJD; 230 }); 231 } 232 233 Error notifyResolved(LinkGraph &G) override { 234 auto &ES = Layer.getExecutionSession(); 235 236 SymbolFlagsMap ExtraSymbolsToClaim; 237 bool AutoClaim = Layer.AutoClaimObjectSymbols; 238 239 SymbolMap InternedResult; 240 for (auto *Sym : G.defined_symbols()) 241 if (Sym->getScope() < Scope::SideEffectsOnly) { 242 auto InternedName = ES.intern(Sym->getName()); 243 auto Ptr = getJITSymbolPtrForSymbol(*Sym, G.getTargetTriple()); 244 auto Flags = getJITSymbolFlagsForSymbol(*Sym); 245 InternedResult[InternedName] = {Ptr, Flags}; 246 if (AutoClaim && !MR->getSymbols().count(InternedName)) { 247 assert(!ExtraSymbolsToClaim.count(InternedName) && 248 "Duplicate symbol to claim?"); 249 ExtraSymbolsToClaim[InternedName] = Flags; 250 } 251 } 252 253 for (auto *Sym : G.absolute_symbols()) 254 if (Sym->getScope() < Scope::SideEffectsOnly) { 255 auto InternedName = ES.intern(Sym->getName()); 256 auto Ptr = getJITSymbolPtrForSymbol(*Sym, G.getTargetTriple()); 257 auto Flags = getJITSymbolFlagsForSymbol(*Sym); 258 InternedResult[InternedName] = {Ptr, Flags}; 259 if (AutoClaim && !MR->getSymbols().count(InternedName)) { 260 assert(!ExtraSymbolsToClaim.count(InternedName) && 261 "Duplicate symbol to claim?"); 262 ExtraSymbolsToClaim[InternedName] = Flags; 263 } 264 } 265 266 if (!ExtraSymbolsToClaim.empty()) 267 if (auto Err = MR->defineMaterializing(ExtraSymbolsToClaim)) 268 return Err; 269 270 { 271 272 // Check that InternedResult matches up with MR->getSymbols(), overriding 273 // flags if requested. 274 // This guards against faulty transformations / compilers / object caches. 275 276 // First check that there aren't any missing symbols. 277 size_t NumMaterializationSideEffectsOnlySymbols = 0; 278 SymbolNameVector MissingSymbols; 279 for (auto &[Sym, Flags] : MR->getSymbols()) { 280 281 auto I = InternedResult.find(Sym); 282 283 // If this is a materialization-side-effects only symbol then bump 284 // the counter and remove in from the result, otherwise make sure that 285 // it's defined. 286 if (Flags.hasMaterializationSideEffectsOnly()) 287 ++NumMaterializationSideEffectsOnlySymbols; 288 else if (I == InternedResult.end()) 289 MissingSymbols.push_back(Sym); 290 else if (Layer.OverrideObjectFlags) 291 I->second.setFlags(Flags); 292 } 293 294 // If there were missing symbols then report the error. 295 if (!MissingSymbols.empty()) 296 return make_error<MissingSymbolDefinitions>( 297 Layer.getExecutionSession().getSymbolStringPool(), G.getName(), 298 std::move(MissingSymbols)); 299 300 // If there are more definitions than expected, add them to the 301 // ExtraSymbols vector. 302 SymbolNameVector ExtraSymbols; 303 if (InternedResult.size() > 304 MR->getSymbols().size() - NumMaterializationSideEffectsOnlySymbols) { 305 for (auto &KV : InternedResult) 306 if (!MR->getSymbols().count(KV.first)) 307 ExtraSymbols.push_back(KV.first); 308 } 309 310 // If there were extra definitions then report the error. 311 if (!ExtraSymbols.empty()) 312 return make_error<UnexpectedSymbolDefinitions>( 313 Layer.getExecutionSession().getSymbolStringPool(), G.getName(), 314 std::move(ExtraSymbols)); 315 } 316 317 if (auto Err = MR->notifyResolved(InternedResult)) 318 return Err; 319 320 notifyLoaded(); 321 return Error::success(); 322 } 323 324 void notifyFinalized(JITLinkMemoryManager::FinalizedAlloc A) override { 325 if (auto Err = notifyEmitted(std::move(A))) { 326 Layer.getExecutionSession().reportError(std::move(Err)); 327 MR->failMaterialization(); 328 return; 329 } 330 331 if (auto Err = MR->notifyEmitted(SymbolDepGroups)) { 332 Layer.getExecutionSession().reportError(std::move(Err)); 333 MR->failMaterialization(); 334 } 335 } 336 337 LinkGraphPassFunction getMarkLivePass(const Triple &TT) const override { 338 return [this](LinkGraph &G) { return markResponsibilitySymbolsLive(G); }; 339 } 340 341 Error modifyPassConfig(LinkGraph &LG, PassConfiguration &Config) override { 342 // Add passes to mark duplicate defs as should-discard, and to walk the 343 // link graph to build the symbol dependence graph. 344 Config.PrePrunePasses.push_back([this](LinkGraph &G) { 345 return claimOrExternalizeWeakAndCommonSymbols(G); 346 }); 347 348 for (auto &P : Plugins) 349 P->modifyPassConfig(*MR, LG, Config); 350 351 Config.PreFixupPasses.push_back( 352 [this](LinkGraph &G) { return registerDependencies(G); }); 353 354 return Error::success(); 355 } 356 357 void notifyLoaded() { 358 for (auto &P : Plugins) 359 P->notifyLoaded(*MR); 360 } 361 362 Error notifyEmitted(jitlink::JITLinkMemoryManager::FinalizedAlloc FA) { 363 Error Err = Error::success(); 364 for (auto &P : Plugins) 365 Err = joinErrors(std::move(Err), P->notifyEmitted(*MR)); 366 367 if (Err) { 368 if (FA) 369 Err = 370 joinErrors(std::move(Err), Layer.MemMgr.deallocate(std::move(FA))); 371 return Err; 372 } 373 374 if (FA) 375 return Layer.recordFinalizedAlloc(*MR, std::move(FA)); 376 377 return Error::success(); 378 } 379 380 private: 381 Error claimOrExternalizeWeakAndCommonSymbols(LinkGraph &G) { 382 auto &ES = Layer.getExecutionSession(); 383 384 SymbolFlagsMap NewSymbolsToClaim; 385 std::vector<std::pair<SymbolStringPtr, Symbol *>> NameToSym; 386 387 auto ProcessSymbol = [&](Symbol *Sym) { 388 if (Sym->hasName() && Sym->getLinkage() == Linkage::Weak && 389 Sym->getScope() != Scope::Local) { 390 auto Name = ES.intern(Sym->getName()); 391 if (!MR->getSymbols().count(ES.intern(Sym->getName()))) { 392 NewSymbolsToClaim[Name] = 393 getJITSymbolFlagsForSymbol(*Sym) | JITSymbolFlags::Weak; 394 NameToSym.push_back(std::make_pair(std::move(Name), Sym)); 395 } 396 } 397 }; 398 399 for (auto *Sym : G.defined_symbols()) 400 ProcessSymbol(Sym); 401 for (auto *Sym : G.absolute_symbols()) 402 ProcessSymbol(Sym); 403 404 // Attempt to claim all weak defs that we're not already responsible for. 405 // This may fail if the resource tracker has become defunct, but should 406 // always succeed otherwise. 407 if (auto Err = MR->defineMaterializing(std::move(NewSymbolsToClaim))) 408 return Err; 409 410 // Walk the list of symbols that we just tried to claim. Symbols that we're 411 // responsible for are marked live. Symbols that we're not responsible for 412 // are turned into external references. 413 for (auto &KV : NameToSym) { 414 if (MR->getSymbols().count(KV.first)) 415 KV.second->setLive(true); 416 else 417 G.makeExternal(*KV.second); 418 } 419 420 return Error::success(); 421 } 422 423 Error markResponsibilitySymbolsLive(LinkGraph &G) const { 424 auto &ES = Layer.getExecutionSession(); 425 for (auto *Sym : G.defined_symbols()) 426 if (Sym->hasName() && MR->getSymbols().count(ES.intern(Sym->getName()))) 427 Sym->setLive(true); 428 return Error::success(); 429 } 430 431 Error registerDependencies(LinkGraph &G) { 432 433 struct BlockInfo { 434 bool InWorklist = false; 435 DenseSet<Symbol *> Defs; 436 DenseSet<Symbol *> SymbolDeps; 437 DenseSet<Block *> AnonEdges, AnonBackEdges; 438 }; 439 440 DenseMap<Block *, BlockInfo> BlockInfos; 441 442 // Reserve space so that BlockInfos doesn't need to resize. This is 443 // essential to avoid invalidating pointers to entries below. 444 { 445 size_t NumBlocks = 0; 446 for (auto &Sec : G.sections()) 447 NumBlocks += Sec.blocks_size(); 448 BlockInfos.reserve(NumBlocks); 449 } 450 451 // Identify non-locally-scoped symbols defined by each block. 452 for (auto *Sym : G.defined_symbols()) { 453 if (Sym->getScope() != Scope::Local) 454 BlockInfos[&Sym->getBlock()].Defs.insert(Sym); 455 } 456 457 // Identify the symbolic and anonymous-block dependencies for each block. 458 for (auto *B : G.blocks()) { 459 auto &BI = BlockInfos[B]; 460 461 for (auto &E : B->edges()) { 462 463 // External symbols are trivially depended on. 464 if (E.getTarget().isExternal()) { 465 BI.SymbolDeps.insert(&E.getTarget()); 466 continue; 467 } 468 469 // Anonymous symbols aren't depended on at all (they're assumed to be 470 // already available). 471 if (E.getTarget().isAbsolute()) 472 continue; 473 474 // If we get here then we depend on a symbol defined by some other 475 // block. 476 auto &TgtBI = BlockInfos[&E.getTarget().getBlock()]; 477 478 // If that block has any definitions then use the first one as the 479 // "effective" dependence here (all symbols in TgtBI will become 480 // ready at the same time, and chosing a single symbol to represent 481 // the block keeps the SymbolDepGroup size small). 482 if (!TgtBI.Defs.empty()) { 483 BI.SymbolDeps.insert(*TgtBI.Defs.begin()); 484 continue; 485 } 486 487 // Otherwise we've got a dependence on an anonymous block. Record it 488 // here for back-propagating symbol dependencies below. 489 BI.AnonEdges.insert(&E.getTarget().getBlock()); 490 TgtBI.AnonBackEdges.insert(B); 491 } 492 } 493 494 // Prune anonymous blocks. 495 { 496 std::vector<Block *> BlocksToRemove; 497 for (auto &[B, BI] : BlockInfos) { 498 // Skip blocks with defs. We only care about anonyous blocks. 499 if (!BI.Defs.empty()) 500 continue; 501 502 BlocksToRemove.push_back(B); 503 504 for (auto *FB : BI.AnonEdges) 505 BlockInfos[FB].AnonBackEdges.erase(B); 506 507 for (auto *BB : BI.AnonBackEdges) 508 BlockInfos[BB].AnonEdges.erase(B); 509 510 for (auto *FB : BI.AnonEdges) { 511 auto &FBI = BlockInfos[FB]; 512 for (auto *BB : BI.AnonBackEdges) 513 FBI.AnonBackEdges.insert(BB); 514 } 515 516 for (auto *BB : BI.AnonBackEdges) { 517 auto &BBI = BlockInfos[BB]; 518 for (auto *SD : BI.SymbolDeps) 519 BBI.SymbolDeps.insert(SD); 520 for (auto *FB : BI.AnonEdges) 521 BBI.AnonEdges.insert(FB); 522 } 523 } 524 525 for (auto *B : BlocksToRemove) 526 BlockInfos.erase(B); 527 } 528 529 // Build the initial dependence propagation worklist. 530 std::deque<Block *> Worklist; 531 for (auto &[B, BI] : BlockInfos) { 532 if (!BI.SymbolDeps.empty() && !BI.AnonBackEdges.empty()) { 533 Worklist.push_back(B); 534 BI.InWorklist = true; 535 } 536 } 537 538 // Propagate symbol deps through the graph. 539 while (!Worklist.empty()) { 540 auto *B = Worklist.front(); 541 Worklist.pop_front(); 542 543 auto &BI = BlockInfos[B]; 544 BI.InWorklist = false; 545 546 for (auto *DB : BI.AnonBackEdges) { 547 auto &DBI = BlockInfos[DB]; 548 for (auto *Sym : BI.SymbolDeps) { 549 if (DBI.SymbolDeps.insert(Sym).second && !DBI.InWorklist) { 550 Worklist.push_back(DB); 551 DBI.InWorklist = true; 552 } 553 } 554 } 555 } 556 557 // Transform our local dependence information into a list of 558 // SymbolDependenceGroups (in the SymbolDepGroups member), ready for use in 559 // the upcoming notifyFinalized call. 560 auto &TargetJD = MR->getTargetJITDylib(); 561 auto &ES = TargetJD.getExecutionSession(); 562 563 DenseMap<Symbol *, SymbolStringPtr> InternedNames; 564 auto GetInternedName = [&](Symbol *S) { 565 auto &Name = InternedNames[S]; 566 if (!Name) 567 Name = ES.intern(S->getName()); 568 return Name; 569 }; 570 571 for (auto &[B, BI] : BlockInfos) { 572 if (!BI.Defs.empty()) { 573 SymbolDepGroups.push_back(SymbolDependenceGroup()); 574 auto &SDG = SymbolDepGroups.back(); 575 576 for (auto *Def : BI.Defs) 577 SDG.Symbols.insert(GetInternedName(Def)); 578 579 for (auto *Dep : BI.SymbolDeps) { 580 auto DepName = GetInternedName(Dep); 581 if (Dep->isDefined()) 582 SDG.Dependencies[&TargetJD].insert(std::move(DepName)); 583 else { 584 auto SourceJDItr = 585 SymbolSourceJDs.find(NonOwningSymbolStringPtr(DepName)); 586 if (SourceJDItr != SymbolSourceJDs.end()) 587 SDG.Dependencies[SourceJDItr->second].insert(std::move(DepName)); 588 } 589 } 590 } 591 } 592 593 return Error::success(); 594 } 595 596 ObjectLinkingLayer &Layer; 597 std::vector<std::shared_ptr<ObjectLinkingLayer::Plugin>> Plugins; 598 std::unique_ptr<MaterializationResponsibility> MR; 599 std::unique_ptr<MemoryBuffer> ObjBuffer; 600 DenseMap<NonOwningSymbolStringPtr, JITDylib *> SymbolSourceJDs; 601 std::vector<SymbolDependenceGroup> SymbolDepGroups; 602 }; 603 604 ObjectLinkingLayer::Plugin::~Plugin() = default; 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 647 if (auto G = createLinkGraphFromObject(ObjBuffer)) { 648 Ctx->notifyMaterializing(**G); 649 link(std::move(*G), std::move(Ctx)); 650 } else { 651 Ctx->notifyFailed(G.takeError()); 652 } 653 } 654 655 void ObjectLinkingLayer::emit(std::unique_ptr<MaterializationResponsibility> R, 656 std::unique_ptr<LinkGraph> G) { 657 auto Ctx = std::make_unique<ObjectLinkingLayerJITLinkContext>( 658 *this, std::move(R), nullptr); 659 Ctx->notifyMaterializing(*G); 660 link(std::move(G), std::move(Ctx)); 661 } 662 663 Error ObjectLinkingLayer::recordFinalizedAlloc( 664 MaterializationResponsibility &MR, FinalizedAlloc FA) { 665 auto Err = MR.withResourceKeyDo( 666 [&](ResourceKey K) { Allocs[K].push_back(std::move(FA)); }); 667 668 if (Err) 669 Err = joinErrors(std::move(Err), MemMgr.deallocate(std::move(FA))); 670 671 return Err; 672 } 673 674 Error ObjectLinkingLayer::handleRemoveResources(JITDylib &JD, ResourceKey K) { 675 676 { 677 Error Err = Error::success(); 678 for (auto &P : Plugins) 679 Err = joinErrors(std::move(Err), P->notifyRemovingResources(JD, K)); 680 if (Err) 681 return Err; 682 } 683 684 std::vector<FinalizedAlloc> AllocsToRemove; 685 getExecutionSession().runSessionLocked([&] { 686 auto I = Allocs.find(K); 687 if (I != Allocs.end()) { 688 std::swap(AllocsToRemove, I->second); 689 Allocs.erase(I); 690 } 691 }); 692 693 if (AllocsToRemove.empty()) 694 return Error::success(); 695 696 return MemMgr.deallocate(std::move(AllocsToRemove)); 697 } 698 699 void ObjectLinkingLayer::handleTransferResources(JITDylib &JD, 700 ResourceKey DstKey, 701 ResourceKey SrcKey) { 702 if (Allocs.contains(SrcKey)) { 703 // DstKey may not be in the DenseMap yet, so the following line may resize 704 // the container and invalidate iterators and value references. 705 auto &DstAllocs = Allocs[DstKey]; 706 auto &SrcAllocs = Allocs[SrcKey]; 707 DstAllocs.reserve(DstAllocs.size() + SrcAllocs.size()); 708 for (auto &Alloc : SrcAllocs) 709 DstAllocs.push_back(std::move(Alloc)); 710 711 Allocs.erase(SrcKey); 712 } 713 714 for (auto &P : Plugins) 715 P->notifyTransferringResources(JD, DstKey, SrcKey); 716 } 717 718 EHFrameRegistrationPlugin::EHFrameRegistrationPlugin( 719 ExecutionSession &ES, std::unique_ptr<EHFrameRegistrar> Registrar) 720 : ES(ES), Registrar(std::move(Registrar)) {} 721 722 void EHFrameRegistrationPlugin::modifyPassConfig( 723 MaterializationResponsibility &MR, LinkGraph &G, 724 PassConfiguration &PassConfig) { 725 726 PassConfig.PostFixupPasses.push_back(createEHFrameRecorderPass( 727 G.getTargetTriple(), [this, &MR](ExecutorAddr Addr, size_t Size) { 728 if (Addr) { 729 std::lock_guard<std::mutex> Lock(EHFramePluginMutex); 730 assert(!InProcessLinks.count(&MR) && 731 "Link for MR already being tracked?"); 732 InProcessLinks[&MR] = {Addr, Size}; 733 } 734 })); 735 } 736 737 Error EHFrameRegistrationPlugin::notifyEmitted( 738 MaterializationResponsibility &MR) { 739 740 ExecutorAddrRange EmittedRange; 741 { 742 std::lock_guard<std::mutex> Lock(EHFramePluginMutex); 743 744 auto EHFrameRangeItr = InProcessLinks.find(&MR); 745 if (EHFrameRangeItr == InProcessLinks.end()) 746 return Error::success(); 747 748 EmittedRange = EHFrameRangeItr->second; 749 assert(EmittedRange.Start && "eh-frame addr to register can not be null"); 750 InProcessLinks.erase(EHFrameRangeItr); 751 } 752 753 if (auto Err = MR.withResourceKeyDo( 754 [&](ResourceKey K) { EHFrameRanges[K].push_back(EmittedRange); })) 755 return Err; 756 757 return Registrar->registerEHFrames(EmittedRange); 758 } 759 760 Error EHFrameRegistrationPlugin::notifyFailed( 761 MaterializationResponsibility &MR) { 762 std::lock_guard<std::mutex> Lock(EHFramePluginMutex); 763 InProcessLinks.erase(&MR); 764 return Error::success(); 765 } 766 767 Error EHFrameRegistrationPlugin::notifyRemovingResources(JITDylib &JD, 768 ResourceKey K) { 769 std::vector<ExecutorAddrRange> RangesToRemove; 770 771 ES.runSessionLocked([&] { 772 auto I = EHFrameRanges.find(K); 773 if (I != EHFrameRanges.end()) { 774 RangesToRemove = std::move(I->second); 775 EHFrameRanges.erase(I); 776 } 777 }); 778 779 Error Err = Error::success(); 780 while (!RangesToRemove.empty()) { 781 auto RangeToRemove = RangesToRemove.back(); 782 RangesToRemove.pop_back(); 783 assert(RangeToRemove.Start && "Untracked eh-frame range must not be null"); 784 Err = joinErrors(std::move(Err), 785 Registrar->deregisterEHFrames(RangeToRemove)); 786 } 787 788 return Err; 789 } 790 791 void EHFrameRegistrationPlugin::notifyTransferringResources( 792 JITDylib &JD, ResourceKey DstKey, ResourceKey SrcKey) { 793 auto SI = EHFrameRanges.find(SrcKey); 794 if (SI == EHFrameRanges.end()) 795 return; 796 797 auto DI = EHFrameRanges.find(DstKey); 798 if (DI != EHFrameRanges.end()) { 799 auto &SrcRanges = SI->second; 800 auto &DstRanges = DI->second; 801 DstRanges.reserve(DstRanges.size() + SrcRanges.size()); 802 for (auto &SrcRange : SrcRanges) 803 DstRanges.push_back(std::move(SrcRange)); 804 EHFrameRanges.erase(SI); 805 } else { 806 // We need to move SrcKey's ranges over without invalidating the SI 807 // iterator. 808 auto Tmp = std::move(SI->second); 809 EHFrameRanges.erase(SI); 810 EHFrameRanges[DstKey] = std::move(Tmp); 811 } 812 } 813 814 } // End namespace orc. 815 } // End namespace llvm. 816