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