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