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(ObjectLinkingLayer &Layer, 28 MaterializationResponsibility MR, 29 std::unique_ptr<MemoryBuffer> ObjBuffer) 30 : Layer(Layer), MR(std::move(MR)), ObjBuffer(std::move(ObjBuffer)) {} 31 32 ~ObjectLinkingLayerJITLinkContext() { 33 // If there is an object buffer return function then use it to 34 // return ownership of the buffer. 35 if (Layer.ReturnObjectBuffer) 36 Layer.ReturnObjectBuffer(std::move(ObjBuffer)); 37 } 38 39 JITLinkMemoryManager &getMemoryManager() override { return Layer.MemMgr; } 40 41 MemoryBufferRef getObjectBuffer() const override { 42 return ObjBuffer->getMemBufferRef(); 43 } 44 45 void notifyFailed(Error Err) override { 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 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 446 ObjectLinkingLayer::ObjectLinkingLayer( 447 ExecutionSession &ES, std::unique_ptr<JITLinkMemoryManager> MemMgr) 448 : ObjectLayer(ES), MemMgr(*MemMgr), MemMgrOwnership(std::move(MemMgr)) {} 449 450 ObjectLinkingLayer::~ObjectLinkingLayer() { 451 if (auto Err = removeAllModules()) 452 getExecutionSession().reportError(std::move(Err)); 453 } 454 455 void ObjectLinkingLayer::emit(MaterializationResponsibility R, 456 std::unique_ptr<MemoryBuffer> O) { 457 assert(O && "Object must not be null"); 458 jitLink(std::make_unique<ObjectLinkingLayerJITLinkContext>( 459 *this, std::move(R), std::move(O))); 460 } 461 462 void ObjectLinkingLayer::modifyPassConfig(MaterializationResponsibility &MR, 463 const Triple &TT, 464 PassConfiguration &PassConfig) { 465 for (auto &P : Plugins) 466 P->modifyPassConfig(MR, TT, PassConfig); 467 } 468 469 void ObjectLinkingLayer::notifyLoaded(MaterializationResponsibility &MR) { 470 for (auto &P : Plugins) 471 P->notifyLoaded(MR); 472 } 473 474 Error ObjectLinkingLayer::notifyEmitted(MaterializationResponsibility &MR, 475 AllocPtr Alloc) { 476 Error Err = Error::success(); 477 for (auto &P : Plugins) 478 Err = joinErrors(std::move(Err), P->notifyEmitted(MR)); 479 480 if (Err) 481 return Err; 482 483 { 484 std::lock_guard<std::mutex> Lock(LayerMutex); 485 UntrackedAllocs.push_back(std::move(Alloc)); 486 } 487 488 return Error::success(); 489 } 490 491 Error ObjectLinkingLayer::removeModule(VModuleKey K) { 492 Error Err = Error::success(); 493 494 for (auto &P : Plugins) 495 Err = joinErrors(std::move(Err), P->notifyRemovingModule(K)); 496 497 AllocPtr Alloc; 498 499 { 500 std::lock_guard<std::mutex> Lock(LayerMutex); 501 auto AllocItr = TrackedAllocs.find(K); 502 Alloc = std::move(AllocItr->second); 503 TrackedAllocs.erase(AllocItr); 504 } 505 506 assert(Alloc && "No allocation for key K"); 507 508 return joinErrors(std::move(Err), Alloc->deallocate()); 509 } 510 511 Error ObjectLinkingLayer::removeAllModules() { 512 513 Error Err = Error::success(); 514 515 for (auto &P : Plugins) 516 Err = joinErrors(std::move(Err), P->notifyRemovingAllModules()); 517 518 std::vector<AllocPtr> Allocs; 519 { 520 std::lock_guard<std::mutex> Lock(LayerMutex); 521 Allocs = std::move(UntrackedAllocs); 522 523 for (auto &KV : TrackedAllocs) 524 Allocs.push_back(std::move(KV.second)); 525 526 TrackedAllocs.clear(); 527 } 528 529 while (!Allocs.empty()) { 530 Err = joinErrors(std::move(Err), Allocs.back()->deallocate()); 531 Allocs.pop_back(); 532 } 533 534 return Err; 535 } 536 537 EHFrameRegistrationPlugin::EHFrameRegistrationPlugin( 538 std::unique_ptr<EHFrameRegistrar> Registrar) 539 : Registrar(std::move(Registrar)) {} 540 541 void EHFrameRegistrationPlugin::modifyPassConfig( 542 MaterializationResponsibility &MR, const Triple &TT, 543 PassConfiguration &PassConfig) { 544 545 PassConfig.PostFixupPasses.push_back(createEHFrameRecorderPass( 546 TT, [this, &MR](JITTargetAddress Addr, size_t Size) { 547 if (Addr) { 548 std::lock_guard<std::mutex> Lock(EHFramePluginMutex); 549 assert(!InProcessLinks.count(&MR) && 550 "Link for MR already being tracked?"); 551 InProcessLinks[&MR] = {Addr, Size}; 552 } 553 })); 554 } 555 556 Error EHFrameRegistrationPlugin::notifyEmitted( 557 MaterializationResponsibility &MR) { 558 std::lock_guard<std::mutex> Lock(EHFramePluginMutex); 559 560 auto EHFrameRangeItr = InProcessLinks.find(&MR); 561 if (EHFrameRangeItr == InProcessLinks.end()) 562 return Error::success(); 563 564 auto EHFrameRange = EHFrameRangeItr->second; 565 assert(EHFrameRange.Addr && 566 "eh-frame addr to register can not be null"); 567 568 InProcessLinks.erase(EHFrameRangeItr); 569 if (auto Key = MR.getVModuleKey()) 570 TrackedEHFrameRanges[Key] = EHFrameRange; 571 else 572 UntrackedEHFrameRanges.push_back(EHFrameRange); 573 574 return Registrar->registerEHFrames(EHFrameRange.Addr, EHFrameRange.Size); 575 } 576 577 Error EHFrameRegistrationPlugin::notifyRemovingModule(VModuleKey K) { 578 std::lock_guard<std::mutex> Lock(EHFramePluginMutex); 579 580 auto EHFrameRangeItr = TrackedEHFrameRanges.find(K); 581 if (EHFrameRangeItr == TrackedEHFrameRanges.end()) 582 return Error::success(); 583 584 auto EHFrameRange = EHFrameRangeItr->second; 585 assert(EHFrameRange.Addr && "Tracked eh-frame range must not be null"); 586 587 TrackedEHFrameRanges.erase(EHFrameRangeItr); 588 589 return Registrar->deregisterEHFrames(EHFrameRange.Addr, EHFrameRange.Size); 590 } 591 592 Error EHFrameRegistrationPlugin::notifyRemovingAllModules() { 593 std::lock_guard<std::mutex> Lock(EHFramePluginMutex); 594 595 std::vector<EHFrameRange> EHFrameRanges = 596 std::move(UntrackedEHFrameRanges); 597 EHFrameRanges.reserve(EHFrameRanges.size() + TrackedEHFrameRanges.size()); 598 599 for (auto &KV : TrackedEHFrameRanges) 600 EHFrameRanges.push_back(KV.second); 601 602 TrackedEHFrameRanges.clear(); 603 604 Error Err = Error::success(); 605 606 while (!EHFrameRanges.empty()) { 607 auto EHFrameRange = EHFrameRanges.back(); 608 assert(EHFrameRange.Addr && "Untracked eh-frame range must not be null"); 609 EHFrameRanges.pop_back(); 610 Err = joinErrors(std::move(Err), Registrar->deregisterEHFrames( 611 EHFrameRange.Addr, EHFrameRange.Size)); 612 } 613 614 return Err; 615 } 616 617 } // End namespace orc. 618 } // End namespace llvm. 619