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