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