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