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