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