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