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