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/DebugUtils.h" 14 #include "llvm/ExecutionEngine/Orc/ObjectFileInterface.h" 15 #include "llvm/ExecutionEngine/Orc/Shared/ObjectFormats.h" 16 #include "llvm/Support/MemoryBuffer.h" 17 18 #include <string> 19 20 #define DEBUG_TYPE "orc" 21 22 using namespace llvm; 23 using namespace llvm::jitlink; 24 using namespace llvm::orc; 25 26 namespace { 27 28 bool hasInitializerSection(jitlink::LinkGraph &G) { 29 bool IsMachO = G.getTargetTriple().isOSBinFormatMachO(); 30 bool IsElf = G.getTargetTriple().isOSBinFormatELF(); 31 if (!IsMachO && !IsElf) 32 return false; 33 34 for (auto &Sec : G.sections()) { 35 if (IsMachO && isMachOInitializerSection(Sec.getName())) 36 return true; 37 if (IsElf && isELFInitializerSection(Sec.getName())) 38 return true; 39 } 40 41 return false; 42 } 43 44 ExecutorAddr getJITSymbolPtrForSymbol(Symbol &Sym, const Triple &TT) { 45 switch (TT.getArch()) { 46 case Triple::arm: 47 case Triple::armeb: 48 case Triple::thumb: 49 case Triple::thumbeb: 50 if (hasTargetFlags(Sym, aarch32::ThumbSymbol)) { 51 // Set LSB to indicate thumb target 52 assert(Sym.isCallable() && "Only callable symbols can have thumb flag"); 53 assert((Sym.getAddress().getValue() & 0x01) == 0 && "LSB is clear"); 54 return Sym.getAddress() + 0x01; 55 } 56 return Sym.getAddress(); 57 default: 58 return Sym.getAddress(); 59 } 60 } 61 62 JITSymbolFlags getJITSymbolFlagsForSymbol(Symbol &Sym) { 63 JITSymbolFlags Flags; 64 65 if (Sym.getLinkage() == Linkage::Weak) 66 Flags |= JITSymbolFlags::Weak; 67 68 if (Sym.getScope() == Scope::Default) 69 Flags |= JITSymbolFlags::Exported; 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->hasName() && Sym->getScope() != Scope::Local) { 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->hasName() && Sym->getScope() != Scope::Local) { 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 ExtraSymbols; 279 SymbolNameVector MissingSymbols; 280 for (auto &KV : MR->getSymbols()) { 281 282 auto I = InternedResult.find(KV.first); 283 284 // If this is a materialization-side-effects only symbol then bump 285 // the counter and make sure it's *not* defined, otherwise make 286 // sure that it is defined. 287 if (KV.second.hasMaterializationSideEffectsOnly()) { 288 ++NumMaterializationSideEffectsOnlySymbols; 289 if (I != InternedResult.end()) 290 ExtraSymbols.push_back(KV.first); 291 continue; 292 } else if (I == InternedResult.end()) 293 MissingSymbols.push_back(KV.first); 294 else if (Layer.OverrideObjectFlags) 295 I->second.setFlags(KV.second); 296 } 297 298 // If there were missing symbols then report the error. 299 if (!MissingSymbols.empty()) 300 return make_error<MissingSymbolDefinitions>( 301 Layer.getExecutionSession().getSymbolStringPool(), G.getName(), 302 std::move(MissingSymbols)); 303 304 // If there are more definitions than expected, add them to the 305 // ExtraSymbols vector. 306 if (InternedResult.size() > 307 MR->getSymbols().size() - NumMaterializationSideEffectsOnlySymbols) { 308 for (auto &KV : InternedResult) 309 if (!MR->getSymbols().count(KV.first)) 310 ExtraSymbols.push_back(KV.first); 311 } 312 313 // If there were extra definitions then report the error. 314 if (!ExtraSymbols.empty()) 315 return make_error<UnexpectedSymbolDefinitions>( 316 Layer.getExecutionSession().getSymbolStringPool(), G.getName(), 317 std::move(ExtraSymbols)); 318 } 319 320 if (auto Err = MR->notifyResolved(InternedResult)) 321 return Err; 322 323 notifyLoaded(); 324 return Error::success(); 325 } 326 327 void notifyFinalized(JITLinkMemoryManager::FinalizedAlloc A) override { 328 if (auto Err = notifyEmitted(std::move(A))) { 329 Layer.getExecutionSession().reportError(std::move(Err)); 330 MR->failMaterialization(); 331 return; 332 } 333 334 if (auto Err = MR->notifyEmitted(SymbolDepGroups)) { 335 Layer.getExecutionSession().reportError(std::move(Err)); 336 MR->failMaterialization(); 337 } 338 } 339 340 LinkGraphPassFunction getMarkLivePass(const Triple &TT) const override { 341 return [this](LinkGraph &G) { return markResponsibilitySymbolsLive(G); }; 342 } 343 344 Error modifyPassConfig(LinkGraph &LG, PassConfiguration &Config) override { 345 // Add passes to mark duplicate defs as should-discard, and to walk the 346 // link graph to build the symbol dependence graph. 347 Config.PrePrunePasses.push_back([this](LinkGraph &G) { 348 return claimOrExternalizeWeakAndCommonSymbols(G); 349 }); 350 351 for (auto &P : Plugins) 352 P->modifyPassConfig(*MR, LG, Config); 353 354 Config.PreFixupPasses.push_back( 355 [this](LinkGraph &G) { return registerDependencies(G); }); 356 357 return Error::success(); 358 } 359 360 void notifyLoaded() { 361 for (auto &P : Plugins) 362 P->notifyLoaded(*MR); 363 } 364 365 Error notifyEmitted(jitlink::JITLinkMemoryManager::FinalizedAlloc FA) { 366 Error Err = Error::success(); 367 for (auto &P : Plugins) 368 Err = joinErrors(std::move(Err), P->notifyEmitted(*MR)); 369 370 if (Err) { 371 if (FA) 372 Err = 373 joinErrors(std::move(Err), Layer.MemMgr.deallocate(std::move(FA))); 374 return Err; 375 } 376 377 if (FA) 378 return Layer.recordFinalizedAlloc(*MR, std::move(FA)); 379 380 return Error::success(); 381 } 382 383 private: 384 Error claimOrExternalizeWeakAndCommonSymbols(LinkGraph &G) { 385 auto &ES = Layer.getExecutionSession(); 386 387 SymbolFlagsMap NewSymbolsToClaim; 388 std::vector<std::pair<SymbolStringPtr, Symbol *>> NameToSym; 389 390 auto ProcessSymbol = [&](Symbol *Sym) { 391 if (Sym->hasName() && Sym->getLinkage() == Linkage::Weak && 392 Sym->getScope() != Scope::Local) { 393 auto Name = ES.intern(Sym->getName()); 394 if (!MR->getSymbols().count(ES.intern(Sym->getName()))) { 395 NewSymbolsToClaim[Name] = 396 getJITSymbolFlagsForSymbol(*Sym) | JITSymbolFlags::Weak; 397 NameToSym.push_back(std::make_pair(std::move(Name), Sym)); 398 } 399 } 400 }; 401 402 for (auto *Sym : G.defined_symbols()) 403 ProcessSymbol(Sym); 404 for (auto *Sym : G.absolute_symbols()) 405 ProcessSymbol(Sym); 406 407 // Attempt to claim all weak defs that we're not already responsible for. 408 // This may fail if the resource tracker has become defunct, but should 409 // always succeed otherwise. 410 if (auto Err = MR->defineMaterializing(std::move(NewSymbolsToClaim))) 411 return Err; 412 413 // Walk the list of symbols that we just tried to claim. Symbols that we're 414 // responsible for are marked live. Symbols that we're not responsible for 415 // are turned into external references. 416 for (auto &KV : NameToSym) { 417 if (MR->getSymbols().count(KV.first)) 418 KV.second->setLive(true); 419 else 420 G.makeExternal(*KV.second); 421 } 422 423 return Error::success(); 424 } 425 426 Error markResponsibilitySymbolsLive(LinkGraph &G) const { 427 auto &ES = Layer.getExecutionSession(); 428 for (auto *Sym : G.defined_symbols()) 429 if (Sym->hasName() && MR->getSymbols().count(ES.intern(Sym->getName()))) 430 Sym->setLive(true); 431 return Error::success(); 432 } 433 434 Error registerDependencies(LinkGraph &G) { 435 436 struct BlockInfo { 437 bool InWorklist = false; 438 DenseSet<Symbol *> Defs; 439 DenseSet<Symbol *> SymbolDeps; 440 DenseSet<Block *> AnonEdges, AnonBackEdges; 441 }; 442 443 DenseMap<Block *, BlockInfo> BlockInfos; 444 445 // Reserve space so that BlockInfos doesn't need to resize. This is 446 // essential to avoid invalidating pointers to entries below. 447 { 448 size_t NumBlocks = 0; 449 for (auto &Sec : G.sections()) 450 NumBlocks += Sec.blocks_size(); 451 BlockInfos.reserve(NumBlocks); 452 } 453 454 // Identify non-locally-scoped symbols defined by each block. 455 for (auto *Sym : G.defined_symbols()) { 456 if (Sym->getScope() != Scope::Local) 457 BlockInfos[&Sym->getBlock()].Defs.insert(Sym); 458 } 459 460 // Identify the symbolic and anonymous-block dependencies for each block. 461 for (auto *B : G.blocks()) { 462 auto &BI = BlockInfos[B]; 463 464 for (auto &E : B->edges()) { 465 466 // External symbols are trivially depended on. 467 if (E.getTarget().isExternal()) { 468 BI.SymbolDeps.insert(&E.getTarget()); 469 continue; 470 } 471 472 // Anonymous symbols aren't depended on at all (they're assumed to be 473 // already available). 474 if (E.getTarget().isAbsolute()) 475 continue; 476 477 // If we get here then we depend on a symbol defined by some other 478 // block. 479 auto &TgtBI = BlockInfos[&E.getTarget().getBlock()]; 480 481 // If that block has any definitions then use the first one as the 482 // "effective" dependence here (all symbols in TgtBI will become 483 // ready at the same time, and chosing a single symbol to represent 484 // the block keeps the SymbolDepGroup size small). 485 if (!TgtBI.Defs.empty()) { 486 BI.SymbolDeps.insert(*TgtBI.Defs.begin()); 487 continue; 488 } 489 490 // Otherwise we've got a dependence on an anonymous block. Record it 491 // here for back-propagating symbol dependencies below. 492 BI.AnonEdges.insert(&E.getTarget().getBlock()); 493 TgtBI.AnonBackEdges.insert(B); 494 } 495 } 496 497 // Prune anonymous blocks. 498 { 499 std::vector<Block *> BlocksToRemove; 500 for (auto &[B, BI] : BlockInfos) { 501 // Skip blocks with defs. We only care about anonyous blocks. 502 if (!BI.Defs.empty()) 503 continue; 504 505 BlocksToRemove.push_back(B); 506 507 for (auto *FB : BI.AnonEdges) 508 BlockInfos[FB].AnonBackEdges.erase(B); 509 510 for (auto *BB : BI.AnonBackEdges) 511 BlockInfos[BB].AnonEdges.erase(B); 512 513 for (auto *FB : BI.AnonEdges) { 514 auto &FBI = BlockInfos[FB]; 515 for (auto *BB : BI.AnonBackEdges) 516 FBI.AnonBackEdges.insert(BB); 517 } 518 519 for (auto *BB : BI.AnonBackEdges) { 520 auto &BBI = BlockInfos[BB]; 521 for (auto *SD : BI.SymbolDeps) 522 BBI.SymbolDeps.insert(SD); 523 for (auto *FB : BI.AnonEdges) 524 BBI.AnonEdges.insert(FB); 525 } 526 } 527 528 for (auto *B : BlocksToRemove) 529 BlockInfos.erase(B); 530 } 531 532 // Build the initial dependence propagation worklist. 533 std::deque<Block *> Worklist; 534 for (auto &[B, BI] : BlockInfos) { 535 if (!BI.SymbolDeps.empty() && !BI.AnonBackEdges.empty()) { 536 Worklist.push_back(B); 537 BI.InWorklist = true; 538 } 539 } 540 541 // Propagate symbol deps through the graph. 542 while (!Worklist.empty()) { 543 auto *B = Worklist.front(); 544 Worklist.pop_front(); 545 546 auto &BI = BlockInfos[B]; 547 BI.InWorklist = false; 548 549 for (auto *DB : BI.AnonBackEdges) { 550 auto &DBI = BlockInfos[DB]; 551 for (auto *Sym : BI.SymbolDeps) { 552 if (DBI.SymbolDeps.insert(Sym).second && !DBI.InWorklist) { 553 Worklist.push_back(DB); 554 DBI.InWorklist = true; 555 } 556 } 557 } 558 } 559 560 // Transform our local dependence information into a list of 561 // SymbolDependenceGroups (in the SymbolDepGroups member), ready for use in 562 // the upcoming notifyFinalized call. 563 auto &TargetJD = MR->getTargetJITDylib(); 564 auto &ES = TargetJD.getExecutionSession(); 565 566 DenseMap<Symbol *, SymbolStringPtr> InternedNames; 567 auto GetInternedName = [&](Symbol *S) { 568 auto &Name = InternedNames[S]; 569 if (!Name) 570 Name = ES.intern(S->getName()); 571 return Name; 572 }; 573 574 for (auto &[B, BI] : BlockInfos) { 575 if (!BI.Defs.empty()) { 576 SymbolDepGroups.push_back(SymbolDependenceGroup()); 577 auto &SDG = SymbolDepGroups.back(); 578 579 for (auto *Def : BI.Defs) 580 SDG.Symbols.insert(GetInternedName(Def)); 581 582 for (auto *Dep : BI.SymbolDeps) { 583 auto DepName = GetInternedName(Dep); 584 if (Dep->isDefined()) 585 SDG.Dependencies[&TargetJD].insert(std::move(DepName)); 586 else { 587 auto SourceJDItr = 588 SymbolSourceJDs.find(NonOwningSymbolStringPtr(DepName)); 589 if (SourceJDItr != SymbolSourceJDs.end()) 590 SDG.Dependencies[SourceJDItr->second].insert(std::move(DepName)); 591 } 592 } 593 } 594 } 595 596 return Error::success(); 597 } 598 599 ObjectLinkingLayer &Layer; 600 std::vector<std::shared_ptr<ObjectLinkingLayer::Plugin>> Plugins; 601 std::unique_ptr<MaterializationResponsibility> MR; 602 std::unique_ptr<MemoryBuffer> ObjBuffer; 603 DenseMap<NonOwningSymbolStringPtr, JITDylib *> SymbolSourceJDs; 604 std::vector<SymbolDependenceGroup> SymbolDepGroups; 605 }; 606 607 ObjectLinkingLayer::Plugin::~Plugin() = default; 608 609 char ObjectLinkingLayer::ID; 610 611 using BaseT = RTTIExtends<ObjectLinkingLayer, ObjectLayer>; 612 613 ObjectLinkingLayer::ObjectLinkingLayer(ExecutionSession &ES) 614 : BaseT(ES), MemMgr(ES.getExecutorProcessControl().getMemMgr()) { 615 ES.registerResourceManager(*this); 616 } 617 618 ObjectLinkingLayer::ObjectLinkingLayer(ExecutionSession &ES, 619 JITLinkMemoryManager &MemMgr) 620 : BaseT(ES), MemMgr(MemMgr) { 621 ES.registerResourceManager(*this); 622 } 623 624 ObjectLinkingLayer::ObjectLinkingLayer( 625 ExecutionSession &ES, std::unique_ptr<JITLinkMemoryManager> MemMgr) 626 : BaseT(ES), MemMgr(*MemMgr), MemMgrOwnership(std::move(MemMgr)) { 627 ES.registerResourceManager(*this); 628 } 629 630 ObjectLinkingLayer::~ObjectLinkingLayer() { 631 assert(Allocs.empty() && "Layer destroyed with resources still attached"); 632 getExecutionSession().deregisterResourceManager(*this); 633 } 634 635 Error ObjectLinkingLayer::add(ResourceTrackerSP RT, 636 std::unique_ptr<LinkGraph> G) { 637 auto &JD = RT->getJITDylib(); 638 return JD.define(LinkGraphMaterializationUnit::Create(*this, std::move(G)), 639 std::move(RT)); 640 } 641 642 void ObjectLinkingLayer::emit(std::unique_ptr<MaterializationResponsibility> R, 643 std::unique_ptr<MemoryBuffer> O) { 644 assert(O && "Object must not be null"); 645 MemoryBufferRef ObjBuffer = O->getMemBufferRef(); 646 647 auto Ctx = std::make_unique<ObjectLinkingLayerJITLinkContext>( 648 *this, std::move(R), std::move(O)); 649 650 if (auto G = createLinkGraphFromObject(ObjBuffer)) { 651 Ctx->notifyMaterializing(**G); 652 link(std::move(*G), std::move(Ctx)); 653 } else { 654 Ctx->notifyFailed(G.takeError()); 655 } 656 } 657 658 void ObjectLinkingLayer::emit(std::unique_ptr<MaterializationResponsibility> R, 659 std::unique_ptr<LinkGraph> G) { 660 auto Ctx = std::make_unique<ObjectLinkingLayerJITLinkContext>( 661 *this, std::move(R), nullptr); 662 Ctx->notifyMaterializing(*G); 663 link(std::move(G), std::move(Ctx)); 664 } 665 666 Error ObjectLinkingLayer::recordFinalizedAlloc( 667 MaterializationResponsibility &MR, FinalizedAlloc FA) { 668 auto Err = MR.withResourceKeyDo( 669 [&](ResourceKey K) { Allocs[K].push_back(std::move(FA)); }); 670 671 if (Err) 672 Err = joinErrors(std::move(Err), MemMgr.deallocate(std::move(FA))); 673 674 return Err; 675 } 676 677 Error ObjectLinkingLayer::handleRemoveResources(JITDylib &JD, ResourceKey K) { 678 679 { 680 Error Err = Error::success(); 681 for (auto &P : Plugins) 682 Err = joinErrors(std::move(Err), P->notifyRemovingResources(JD, K)); 683 if (Err) 684 return Err; 685 } 686 687 std::vector<FinalizedAlloc> AllocsToRemove; 688 getExecutionSession().runSessionLocked([&] { 689 auto I = Allocs.find(K); 690 if (I != Allocs.end()) { 691 std::swap(AllocsToRemove, I->second); 692 Allocs.erase(I); 693 } 694 }); 695 696 if (AllocsToRemove.empty()) 697 return Error::success(); 698 699 return MemMgr.deallocate(std::move(AllocsToRemove)); 700 } 701 702 void ObjectLinkingLayer::handleTransferResources(JITDylib &JD, 703 ResourceKey DstKey, 704 ResourceKey SrcKey) { 705 auto I = Allocs.find(SrcKey); 706 if (I != Allocs.end()) { 707 auto &SrcAllocs = I->second; 708 auto &DstAllocs = Allocs[DstKey]; 709 DstAllocs.reserve(DstAllocs.size() + SrcAllocs.size()); 710 for (auto &Alloc : SrcAllocs) 711 DstAllocs.push_back(std::move(Alloc)); 712 713 // Erase SrcKey entry using value rather than iterator I: I may have been 714 // invalidated when we looked up DstKey. 715 Allocs.erase(SrcKey); 716 } 717 718 for (auto &P : Plugins) 719 P->notifyTransferringResources(JD, DstKey, SrcKey); 720 } 721 722 EHFrameRegistrationPlugin::EHFrameRegistrationPlugin( 723 ExecutionSession &ES, std::unique_ptr<EHFrameRegistrar> Registrar) 724 : ES(ES), Registrar(std::move(Registrar)) {} 725 726 void EHFrameRegistrationPlugin::modifyPassConfig( 727 MaterializationResponsibility &MR, LinkGraph &G, 728 PassConfiguration &PassConfig) { 729 730 PassConfig.PostFixupPasses.push_back(createEHFrameRecorderPass( 731 G.getTargetTriple(), [this, &MR](ExecutorAddr Addr, size_t Size) { 732 if (Addr) { 733 std::lock_guard<std::mutex> Lock(EHFramePluginMutex); 734 assert(!InProcessLinks.count(&MR) && 735 "Link for MR already being tracked?"); 736 InProcessLinks[&MR] = {Addr, Size}; 737 } 738 })); 739 } 740 741 Error EHFrameRegistrationPlugin::notifyEmitted( 742 MaterializationResponsibility &MR) { 743 744 ExecutorAddrRange EmittedRange; 745 { 746 std::lock_guard<std::mutex> Lock(EHFramePluginMutex); 747 748 auto EHFrameRangeItr = InProcessLinks.find(&MR); 749 if (EHFrameRangeItr == InProcessLinks.end()) 750 return Error::success(); 751 752 EmittedRange = EHFrameRangeItr->second; 753 assert(EmittedRange.Start && "eh-frame addr to register can not be null"); 754 InProcessLinks.erase(EHFrameRangeItr); 755 } 756 757 if (auto Err = MR.withResourceKeyDo( 758 [&](ResourceKey K) { EHFrameRanges[K].push_back(EmittedRange); })) 759 return Err; 760 761 return Registrar->registerEHFrames(EmittedRange); 762 } 763 764 Error EHFrameRegistrationPlugin::notifyFailed( 765 MaterializationResponsibility &MR) { 766 std::lock_guard<std::mutex> Lock(EHFramePluginMutex); 767 InProcessLinks.erase(&MR); 768 return Error::success(); 769 } 770 771 Error EHFrameRegistrationPlugin::notifyRemovingResources(JITDylib &JD, 772 ResourceKey K) { 773 std::vector<ExecutorAddrRange> RangesToRemove; 774 775 ES.runSessionLocked([&] { 776 auto I = EHFrameRanges.find(K); 777 if (I != EHFrameRanges.end()) { 778 RangesToRemove = std::move(I->second); 779 EHFrameRanges.erase(I); 780 } 781 }); 782 783 Error Err = Error::success(); 784 while (!RangesToRemove.empty()) { 785 auto RangeToRemove = RangesToRemove.back(); 786 RangesToRemove.pop_back(); 787 assert(RangeToRemove.Start && "Untracked eh-frame range must not be null"); 788 Err = joinErrors(std::move(Err), 789 Registrar->deregisterEHFrames(RangeToRemove)); 790 } 791 792 return Err; 793 } 794 795 void EHFrameRegistrationPlugin::notifyTransferringResources( 796 JITDylib &JD, ResourceKey DstKey, ResourceKey SrcKey) { 797 auto SI = EHFrameRanges.find(SrcKey); 798 if (SI == EHFrameRanges.end()) 799 return; 800 801 auto DI = EHFrameRanges.find(DstKey); 802 if (DI != EHFrameRanges.end()) { 803 auto &SrcRanges = SI->second; 804 auto &DstRanges = DI->second; 805 DstRanges.reserve(DstRanges.size() + SrcRanges.size()); 806 for (auto &SrcRange : SrcRanges) 807 DstRanges.push_back(std::move(SrcRange)); 808 EHFrameRanges.erase(SI); 809 } else { 810 // We need to move SrcKey's ranges over without invalidating the SI 811 // iterator. 812 auto Tmp = std::move(SI->second); 813 EHFrameRanges.erase(SI); 814 EHFrameRanges[DstKey] = std::move(Tmp); 815 } 816 } 817 818 } // End namespace orc. 819 } // End namespace llvm. 820