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 11 #include "llvm/ADT/Optional.h" 12 #include "llvm/ExecutionEngine/JITLink/EHFrameSupport.h" 13 14 #include <vector> 15 16 #define DEBUG_TYPE "orc" 17 18 using namespace llvm; 19 using namespace llvm::jitlink; 20 using namespace llvm::orc; 21 22 namespace llvm { 23 namespace orc { 24 25 class ObjectLinkingLayerJITLinkContext final : public JITLinkContext { 26 public: 27 ObjectLinkingLayerJITLinkContext( 28 ObjectLinkingLayer &Layer, 29 std::unique_ptr<MaterializationResponsibility> MR, 30 std::unique_ptr<MemoryBuffer> ObjBuffer) 31 : JITLinkContext(&MR->getTargetJITDylib()), Layer(Layer), 32 MR(std::move(MR)), ObjBuffer(std::move(ObjBuffer)) {} 33 34 ~ObjectLinkingLayerJITLinkContext() { 35 // If there is an object buffer return function then use it to 36 // return ownership of the buffer. 37 if (Layer.ReturnObjectBuffer && ObjBuffer) 38 Layer.ReturnObjectBuffer(std::move(ObjBuffer)); 39 } 40 41 JITLinkMemoryManager &getMemoryManager() override { return Layer.MemMgr; } 42 43 void notifyFailed(Error Err) override { 44 for (auto &P : Layer.Plugins) 45 Err = joinErrors(std::move(Err), P->notifyFailed(*MR)); 46 Layer.getExecutionSession().reportError(std::move(Err)); 47 MR->failMaterialization(); 48 } 49 50 void lookup(const LookupMap &Symbols, 51 std::unique_ptr<JITLinkAsyncLookupContinuation> LC) override { 52 53 JITDylibSearchOrder LinkOrder; 54 MR->getTargetJITDylib().withLinkOrderDo( 55 [&](const JITDylibSearchOrder &LO) { LinkOrder = LO; }); 56 57 auto &ES = Layer.getExecutionSession(); 58 59 SymbolLookupSet LookupSet; 60 for (auto &KV : Symbols) { 61 orc::SymbolLookupFlags LookupFlags; 62 switch (KV.second) { 63 case jitlink::SymbolLookupFlags::RequiredSymbol: 64 LookupFlags = orc::SymbolLookupFlags::RequiredSymbol; 65 break; 66 case jitlink::SymbolLookupFlags::WeaklyReferencedSymbol: 67 LookupFlags = orc::SymbolLookupFlags::WeaklyReferencedSymbol; 68 break; 69 } 70 LookupSet.add(ES.intern(KV.first), LookupFlags); 71 } 72 73 // OnResolve -- De-intern the symbols and pass the result to the linker. 74 auto OnResolve = [LookupContinuation = 75 std::move(LC)](Expected<SymbolMap> Result) mutable { 76 if (!Result) 77 LookupContinuation->run(Result.takeError()); 78 else { 79 AsyncLookupResult LR; 80 for (auto &KV : *Result) 81 LR[*KV.first] = KV.second; 82 LookupContinuation->run(std::move(LR)); 83 } 84 }; 85 86 for (auto &KV : InternalNamedSymbolDeps) { 87 SymbolDependenceMap InternalDeps; 88 InternalDeps[&MR->getTargetJITDylib()] = std::move(KV.second); 89 MR->addDependencies(KV.first, InternalDeps); 90 } 91 92 ES.lookup(LookupKind::Static, LinkOrder, std::move(LookupSet), 93 SymbolState::Resolved, std::move(OnResolve), 94 [this](const SymbolDependenceMap &Deps) { 95 registerDependencies(Deps); 96 }); 97 } 98 99 Error notifyResolved(LinkGraph &G) override { 100 auto &ES = Layer.getExecutionSession(); 101 102 SymbolFlagsMap ExtraSymbolsToClaim; 103 bool AutoClaim = Layer.AutoClaimObjectSymbols; 104 105 SymbolMap InternedResult; 106 for (auto *Sym : G.defined_symbols()) 107 if (Sym->hasName() && Sym->getScope() != Scope::Local) { 108 auto InternedName = ES.intern(Sym->getName()); 109 JITSymbolFlags Flags; 110 111 if (Sym->isCallable()) 112 Flags |= JITSymbolFlags::Callable; 113 if (Sym->getScope() == Scope::Default) 114 Flags |= JITSymbolFlags::Exported; 115 116 InternedResult[InternedName] = 117 JITEvaluatedSymbol(Sym->getAddress(), Flags); 118 if (AutoClaim && !MR->getSymbols().count(InternedName)) { 119 assert(!ExtraSymbolsToClaim.count(InternedName) && 120 "Duplicate symbol to claim?"); 121 ExtraSymbolsToClaim[InternedName] = Flags; 122 } 123 } 124 125 for (auto *Sym : G.absolute_symbols()) 126 if (Sym->hasName()) { 127 auto InternedName = ES.intern(Sym->getName()); 128 JITSymbolFlags Flags; 129 Flags |= JITSymbolFlags::Absolute; 130 if (Sym->isCallable()) 131 Flags |= JITSymbolFlags::Callable; 132 if (Sym->getLinkage() == Linkage::Weak) 133 Flags |= JITSymbolFlags::Weak; 134 InternedResult[InternedName] = 135 JITEvaluatedSymbol(Sym->getAddress(), Flags); 136 if (AutoClaim && !MR->getSymbols().count(InternedName)) { 137 assert(!ExtraSymbolsToClaim.count(InternedName) && 138 "Duplicate symbol to claim?"); 139 ExtraSymbolsToClaim[InternedName] = Flags; 140 } 141 } 142 143 if (!ExtraSymbolsToClaim.empty()) 144 if (auto Err = MR->defineMaterializing(ExtraSymbolsToClaim)) 145 return Err; 146 147 { 148 149 // Check that InternedResult matches up with MR->getSymbols(). 150 // This guards against faulty transformations / compilers / object caches. 151 152 // First check that there aren't any missing symbols. 153 size_t NumMaterializationSideEffectsOnlySymbols = 0; 154 SymbolNameVector ExtraSymbols; 155 SymbolNameVector MissingSymbols; 156 for (auto &KV : MR->getSymbols()) { 157 158 // If this is a materialization-side-effects only symbol then bump 159 // the counter and make sure it's *not* defined, otherwise make 160 // sure that it is defined. 161 if (KV.second.hasMaterializationSideEffectsOnly()) { 162 ++NumMaterializationSideEffectsOnlySymbols; 163 if (InternedResult.count(KV.first)) 164 ExtraSymbols.push_back(KV.first); 165 continue; 166 } else if (!InternedResult.count(KV.first)) 167 MissingSymbols.push_back(KV.first); 168 } 169 170 // If there were missing symbols then report the error. 171 if (!MissingSymbols.empty()) 172 return make_error<MissingSymbolDefinitions>(G.getName(), 173 std::move(MissingSymbols)); 174 175 // If there are more definitions than expected, add them to the 176 // ExtraSymbols vector. 177 if (InternedResult.size() > 178 MR->getSymbols().size() - NumMaterializationSideEffectsOnlySymbols) { 179 for (auto &KV : InternedResult) 180 if (!MR->getSymbols().count(KV.first)) 181 ExtraSymbols.push_back(KV.first); 182 } 183 184 // If there were extra definitions then report the error. 185 if (!ExtraSymbols.empty()) 186 return make_error<UnexpectedSymbolDefinitions>(G.getName(), 187 std::move(ExtraSymbols)); 188 } 189 190 if (auto Err = MR->notifyResolved(InternedResult)) 191 return Err; 192 193 Layer.notifyLoaded(*MR); 194 return Error::success(); 195 } 196 197 void notifyFinalized( 198 std::unique_ptr<JITLinkMemoryManager::Allocation> A) override { 199 if (auto Err = Layer.notifyEmitted(*MR, std::move(A))) { 200 Layer.getExecutionSession().reportError(std::move(Err)); 201 MR->failMaterialization(); 202 return; 203 } 204 if (auto Err = MR->notifyEmitted()) { 205 Layer.getExecutionSession().reportError(std::move(Err)); 206 MR->failMaterialization(); 207 } 208 } 209 210 LinkGraphPassFunction getMarkLivePass(const Triple &TT) const override { 211 return [this](LinkGraph &G) { return markResponsibilitySymbolsLive(G); }; 212 } 213 214 Error modifyPassConfig(const Triple &TT, PassConfiguration &Config) override { 215 // Add passes to mark duplicate defs as should-discard, and to walk the 216 // link graph to build the symbol dependence graph. 217 Config.PrePrunePasses.push_back( 218 [this](LinkGraph &G) { return externalizeWeakAndCommonSymbols(G); }); 219 220 Layer.modifyPassConfig(*MR, TT, Config); 221 222 Config.PostPrunePasses.push_back( 223 [this](LinkGraph &G) { return computeNamedSymbolDependencies(G); }); 224 225 return Error::success(); 226 } 227 228 private: 229 struct LocalSymbolNamedDependencies { 230 SymbolNameSet Internal, External; 231 }; 232 233 using LocalSymbolNamedDependenciesMap = 234 DenseMap<const Symbol *, LocalSymbolNamedDependencies>; 235 236 Error externalizeWeakAndCommonSymbols(LinkGraph &G) { 237 auto &ES = Layer.getExecutionSession(); 238 for (auto *Sym : G.defined_symbols()) 239 if (Sym->hasName() && Sym->getLinkage() == Linkage::Weak) { 240 if (!MR->getSymbols().count(ES.intern(Sym->getName()))) 241 G.makeExternal(*Sym); 242 } 243 244 for (auto *Sym : G.absolute_symbols()) 245 if (Sym->hasName() && Sym->getLinkage() == Linkage::Weak) { 246 if (!MR->getSymbols().count(ES.intern(Sym->getName()))) 247 G.makeExternal(*Sym); 248 } 249 250 return Error::success(); 251 } 252 253 Error markResponsibilitySymbolsLive(LinkGraph &G) const { 254 auto &ES = Layer.getExecutionSession(); 255 for (auto *Sym : G.defined_symbols()) 256 if (Sym->hasName() && MR->getSymbols().count(ES.intern(Sym->getName()))) 257 Sym->setLive(true); 258 return Error::success(); 259 } 260 261 Error computeNamedSymbolDependencies(LinkGraph &G) { 262 auto &ES = MR->getTargetJITDylib().getExecutionSession(); 263 auto LocalDeps = computeLocalDeps(G); 264 265 // Compute dependencies for symbols defined in the JITLink graph. 266 for (auto *Sym : G.defined_symbols()) { 267 268 // Skip local symbols: we do not track dependencies for these. 269 if (Sym->getScope() == Scope::Local) 270 continue; 271 assert(Sym->hasName() && 272 "Defined non-local jitlink::Symbol should have a name"); 273 274 SymbolNameSet ExternalSymDeps, InternalSymDeps; 275 276 // Find internal and external named symbol dependencies. 277 for (auto &E : Sym->getBlock().edges()) { 278 auto &TargetSym = E.getTarget(); 279 280 if (TargetSym.getScope() != Scope::Local) { 281 if (TargetSym.isExternal()) 282 ExternalSymDeps.insert(ES.intern(TargetSym.getName())); 283 else if (&TargetSym != Sym) 284 InternalSymDeps.insert(ES.intern(TargetSym.getName())); 285 } else { 286 assert(TargetSym.isDefined() && 287 "local symbols must be defined"); 288 auto I = LocalDeps.find(&TargetSym); 289 if (I != LocalDeps.end()) { 290 for (auto &S : I->second.External) 291 ExternalSymDeps.insert(S); 292 for (auto &S : I->second.Internal) 293 InternalSymDeps.insert(S); 294 } 295 } 296 } 297 298 if (ExternalSymDeps.empty() && InternalSymDeps.empty()) 299 continue; 300 301 auto SymName = ES.intern(Sym->getName()); 302 if (!ExternalSymDeps.empty()) 303 ExternalNamedSymbolDeps[SymName] = std::move(ExternalSymDeps); 304 if (!InternalSymDeps.empty()) 305 InternalNamedSymbolDeps[SymName] = std::move(InternalSymDeps); 306 } 307 308 for (auto &P : Layer.Plugins) { 309 auto SyntheticLocalDeps = P->getSyntheticSymbolLocalDependencies(*MR); 310 if (SyntheticLocalDeps.empty()) 311 continue; 312 313 for (auto &KV : SyntheticLocalDeps) { 314 auto &Name = KV.first; 315 auto &LocalDepsForName = KV.second; 316 for (auto *Local : LocalDepsForName) { 317 assert(Local->getScope() == Scope::Local && 318 "Dependence on non-local symbol"); 319 auto LocalNamedDepsItr = LocalDeps.find(Local); 320 if (LocalNamedDepsItr == LocalDeps.end()) 321 continue; 322 for (auto &S : LocalNamedDepsItr->second.Internal) 323 InternalNamedSymbolDeps[Name].insert(S); 324 for (auto &S : LocalNamedDepsItr->second.External) 325 ExternalNamedSymbolDeps[Name].insert(S); 326 } 327 } 328 } 329 330 return Error::success(); 331 } 332 333 LocalSymbolNamedDependenciesMap computeLocalDeps(LinkGraph &G) { 334 DenseMap<jitlink::Symbol *, DenseSet<jitlink::Symbol *>> DepMap; 335 336 // For all local symbols: 337 // (1) Add their named dependencies. 338 // (2) Add them to the worklist for further iteration if they have any 339 // depend on any other local symbols. 340 struct WorklistEntry { 341 WorklistEntry(Symbol *Sym, DenseSet<Symbol *> LocalDeps) 342 : Sym(Sym), LocalDeps(std::move(LocalDeps)) {} 343 344 Symbol *Sym = nullptr; 345 DenseSet<Symbol *> LocalDeps; 346 }; 347 std::vector<WorklistEntry> Worklist; 348 for (auto *Sym : G.defined_symbols()) 349 if (Sym->getScope() == Scope::Local) { 350 auto &SymNamedDeps = DepMap[Sym]; 351 DenseSet<Symbol *> LocalDeps; 352 353 for (auto &E : Sym->getBlock().edges()) { 354 auto &TargetSym = E.getTarget(); 355 if (TargetSym.getScope() != Scope::Local) 356 SymNamedDeps.insert(&TargetSym); 357 else { 358 assert(TargetSym.isDefined() && 359 "local symbols must be defined"); 360 LocalDeps.insert(&TargetSym); 361 } 362 } 363 364 if (!LocalDeps.empty()) 365 Worklist.push_back(WorklistEntry(Sym, std::move(LocalDeps))); 366 } 367 368 // Loop over all local symbols with local dependencies, propagating 369 // their respective non-local dependencies. Iterate until we hit a stable 370 // state. 371 bool Changed; 372 do { 373 Changed = false; 374 for (auto &WLEntry : Worklist) { 375 auto *Sym = WLEntry.Sym; 376 auto &NamedDeps = DepMap[Sym]; 377 auto &LocalDeps = WLEntry.LocalDeps; 378 379 for (auto *TargetSym : LocalDeps) { 380 auto I = DepMap.find(TargetSym); 381 if (I != DepMap.end()) 382 for (const auto &S : I->second) 383 Changed |= NamedDeps.insert(S).second; 384 } 385 } 386 } while (Changed); 387 388 // Intern the results to produce a mapping of jitlink::Symbol* to internal 389 // and external symbol names. 390 auto &ES = Layer.getExecutionSession(); 391 LocalSymbolNamedDependenciesMap Result; 392 for (auto &KV : DepMap) { 393 auto *Local = KV.first; 394 assert(Local->getScope() == Scope::Local && 395 "DepMap keys should all be local symbols"); 396 auto &LocalNamedDeps = Result[Local]; 397 for (auto *Named : KV.second) { 398 assert(Named->getScope() != Scope::Local && 399 "DepMap values should all be non-local symbol sets"); 400 if (Named->isExternal()) 401 LocalNamedDeps.External.insert(ES.intern(Named->getName())); 402 else 403 LocalNamedDeps.Internal.insert(ES.intern(Named->getName())); 404 } 405 } 406 407 return Result; 408 } 409 410 void registerDependencies(const SymbolDependenceMap &QueryDeps) { 411 for (auto &NamedDepsEntry : ExternalNamedSymbolDeps) { 412 auto &Name = NamedDepsEntry.first; 413 auto &NameDeps = NamedDepsEntry.second; 414 SymbolDependenceMap SymbolDeps; 415 416 for (const auto &QueryDepsEntry : QueryDeps) { 417 JITDylib &SourceJD = *QueryDepsEntry.first; 418 const SymbolNameSet &Symbols = QueryDepsEntry.second; 419 auto &DepsForJD = SymbolDeps[&SourceJD]; 420 421 for (const auto &S : Symbols) 422 if (NameDeps.count(S)) 423 DepsForJD.insert(S); 424 425 if (DepsForJD.empty()) 426 SymbolDeps.erase(&SourceJD); 427 } 428 429 MR->addDependencies(Name, SymbolDeps); 430 } 431 } 432 433 ObjectLinkingLayer &Layer; 434 std::unique_ptr<MaterializationResponsibility> MR; 435 std::unique_ptr<MemoryBuffer> ObjBuffer; 436 DenseMap<SymbolStringPtr, SymbolNameSet> ExternalNamedSymbolDeps; 437 DenseMap<SymbolStringPtr, SymbolNameSet> InternalNamedSymbolDeps; 438 }; 439 440 ObjectLinkingLayer::Plugin::~Plugin() {} 441 442 ObjectLinkingLayer::ObjectLinkingLayer(ExecutionSession &ES, 443 JITLinkMemoryManager &MemMgr) 444 : ObjectLayer(ES), MemMgr(MemMgr) { 445 ES.registerResourceManager(*this); 446 } 447 448 ObjectLinkingLayer::ObjectLinkingLayer( 449 ExecutionSession &ES, std::unique_ptr<JITLinkMemoryManager> MemMgr) 450 : ObjectLayer(ES), MemMgr(*MemMgr), MemMgrOwnership(std::move(MemMgr)) { 451 ES.registerResourceManager(*this); 452 } 453 454 ObjectLinkingLayer::~ObjectLinkingLayer() { 455 assert(Allocs.empty() && "Layer destroyed with resources still attached"); 456 getExecutionSession().deregisterResourceManager(*this); 457 } 458 459 void ObjectLinkingLayer::emit(std::unique_ptr<MaterializationResponsibility> R, 460 std::unique_ptr<MemoryBuffer> O) { 461 assert(O && "Object must not be null"); 462 auto ObjBuffer = O->getMemBufferRef(); 463 auto Ctx = std::make_unique<ObjectLinkingLayerJITLinkContext>( 464 *this, std::move(R), std::move(O)); 465 if (auto G = createLinkGraphFromObject(std::move(ObjBuffer))) 466 link(std::move(*G), std::move(Ctx)); 467 else 468 Ctx->notifyFailed(G.takeError()); 469 } 470 471 void ObjectLinkingLayer::emit(std::unique_ptr<MaterializationResponsibility> R, 472 std::unique_ptr<LinkGraph> G) { 473 link(std::move(G), std::make_unique<ObjectLinkingLayerJITLinkContext>( 474 *this, std::move(R), nullptr)); 475 } 476 477 void ObjectLinkingLayer::modifyPassConfig(MaterializationResponsibility &MR, 478 const Triple &TT, 479 PassConfiguration &PassConfig) { 480 for (auto &P : Plugins) 481 P->modifyPassConfig(MR, TT, PassConfig); 482 } 483 484 void ObjectLinkingLayer::notifyLoaded(MaterializationResponsibility &MR) { 485 for (auto &P : Plugins) 486 P->notifyLoaded(MR); 487 } 488 489 Error ObjectLinkingLayer::notifyEmitted(MaterializationResponsibility &MR, 490 AllocPtr Alloc) { 491 Error Err = Error::success(); 492 for (auto &P : Plugins) 493 Err = joinErrors(std::move(Err), P->notifyEmitted(MR)); 494 495 if (Err) 496 return Err; 497 498 return MR.withResourceKeyDo( 499 [&](ResourceKey K) { Allocs[K].push_back(std::move(Alloc)); }); 500 } 501 502 Error ObjectLinkingLayer::handleRemoveResources(ResourceKey K) { 503 504 Error Err = Error::success(); 505 506 for (auto &P : Plugins) 507 Err = joinErrors(std::move(Err), P->notifyRemovingResources(K)); 508 509 std::vector<AllocPtr> AllocsToRemove; 510 getExecutionSession().runSessionLocked([&] { 511 auto I = Allocs.find(K); 512 if (I != Allocs.end()) { 513 std::swap(AllocsToRemove, I->second); 514 Allocs.erase(I); 515 } 516 }); 517 518 while (!AllocsToRemove.empty()) { 519 Err = joinErrors(std::move(Err), AllocsToRemove.back()->deallocate()); 520 AllocsToRemove.pop_back(); 521 } 522 523 return Err; 524 } 525 526 void ObjectLinkingLayer::handleTransferResources(ResourceKey DstKey, 527 ResourceKey SrcKey) { 528 auto I = Allocs.find(SrcKey); 529 if (I != Allocs.end()) { 530 auto &SrcAllocs = I->second; 531 auto &DstAllocs = Allocs[DstKey]; 532 DstAllocs.reserve(DstAllocs.size() + SrcAllocs.size()); 533 for (auto &Alloc : SrcAllocs) 534 DstAllocs.push_back(std::move(Alloc)); 535 536 // Erase SrcKey entry using value rather than iterator I: I may have been 537 // invalidated when we looked up DstKey. 538 Allocs.erase(SrcKey); 539 } 540 541 for (auto &P : Plugins) 542 P->notifyTransferringResources(DstKey, SrcKey); 543 } 544 545 EHFrameRegistrationPlugin::EHFrameRegistrationPlugin( 546 ExecutionSession &ES, std::unique_ptr<EHFrameRegistrar> Registrar) 547 : ES(ES), Registrar(std::move(Registrar)) {} 548 549 void EHFrameRegistrationPlugin::modifyPassConfig( 550 MaterializationResponsibility &MR, const Triple &TT, 551 PassConfiguration &PassConfig) { 552 553 PassConfig.PostFixupPasses.push_back(createEHFrameRecorderPass( 554 TT, [this, &MR](JITTargetAddress Addr, size_t Size) { 555 if (Addr) { 556 std::lock_guard<std::mutex> Lock(EHFramePluginMutex); 557 assert(!InProcessLinks.count(&MR) && 558 "Link for MR already being tracked?"); 559 InProcessLinks[&MR] = {Addr, Size}; 560 } 561 })); 562 } 563 564 Error EHFrameRegistrationPlugin::notifyEmitted( 565 MaterializationResponsibility &MR) { 566 567 EHFrameRange EmittedRange; 568 { 569 std::lock_guard<std::mutex> Lock(EHFramePluginMutex); 570 571 auto EHFrameRangeItr = InProcessLinks.find(&MR); 572 if (EHFrameRangeItr == InProcessLinks.end()) 573 return Error::success(); 574 575 EmittedRange = EHFrameRangeItr->second; 576 assert(EmittedRange.Addr && "eh-frame addr to register can not be null"); 577 InProcessLinks.erase(EHFrameRangeItr); 578 } 579 580 if (auto Err = MR.withResourceKeyDo( 581 [&](ResourceKey K) { EHFrameRanges[K].push_back(EmittedRange); })) 582 return Err; 583 584 return Registrar->registerEHFrames(EmittedRange.Addr, EmittedRange.Size); 585 } 586 587 Error EHFrameRegistrationPlugin::notifyFailed( 588 MaterializationResponsibility &MR) { 589 std::lock_guard<std::mutex> Lock(EHFramePluginMutex); 590 InProcessLinks.erase(&MR); 591 return Error::success(); 592 } 593 594 Error EHFrameRegistrationPlugin::notifyRemovingResources(ResourceKey K) { 595 std::vector<EHFrameRange> RangesToRemove; 596 597 ES.runSessionLocked([&] { 598 auto I = EHFrameRanges.find(K); 599 if (I != EHFrameRanges.end()) { 600 RangesToRemove = std::move(I->second); 601 EHFrameRanges.erase(I); 602 } 603 }); 604 605 Error Err = Error::success(); 606 while (!RangesToRemove.empty()) { 607 auto RangeToRemove = RangesToRemove.back(); 608 RangesToRemove.pop_back(); 609 assert(RangeToRemove.Addr && "Untracked eh-frame range must not be null"); 610 Err = joinErrors( 611 std::move(Err), 612 Registrar->deregisterEHFrames(RangeToRemove.Addr, RangeToRemove.Size)); 613 } 614 615 return Err; 616 } 617 618 void EHFrameRegistrationPlugin::notifyTransferringResources( 619 ResourceKey DstKey, ResourceKey SrcKey) { 620 auto SI = EHFrameRanges.find(SrcKey); 621 if (SI != EHFrameRanges.end()) { 622 auto &SrcRanges = SI->second; 623 auto &DstRanges = EHFrameRanges[DstKey]; 624 DstRanges.reserve(DstRanges.size() + SrcRanges.size()); 625 for (auto &SrcRange : SrcRanges) 626 DstRanges.push_back(std::move(SrcRange)); 627 EHFrameRanges.erase(SI); 628 } 629 } 630 631 } // End namespace orc. 632 } // End namespace llvm. 633