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