1 //===------ LinkGraphLinkingLayer.cpp - Link LinkGraphs with JITLink ------===// 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/LinkGraphLinkingLayer.h" 10 #include "llvm/ExecutionEngine/JITLink/EHFrameSupport.h" 11 #include "llvm/ExecutionEngine/JITLink/aarch32.h" 12 #include "llvm/ExecutionEngine/Orc/DebugUtils.h" 13 #include "llvm/ExecutionEngine/Orc/Shared/ObjectFormats.h" 14 #include "llvm/Support/MemoryBuffer.h" 15 16 #define DEBUG_TYPE "orc" 17 18 using namespace llvm; 19 using namespace llvm::jitlink; 20 using namespace llvm::orc; 21 22 namespace { 23 24 ExecutorAddr getJITSymbolPtrForSymbol(Symbol &Sym, const Triple &TT) { 25 switch (TT.getArch()) { 26 case Triple::arm: 27 case Triple::armeb: 28 case Triple::thumb: 29 case Triple::thumbeb: 30 if (hasTargetFlags(Sym, aarch32::ThumbSymbol)) { 31 // Set LSB to indicate thumb target 32 assert(Sym.isCallable() && "Only callable symbols can have thumb flag"); 33 assert((Sym.getAddress().getValue() & 0x01) == 0 && "LSB is clear"); 34 return Sym.getAddress() + 0x01; 35 } 36 return Sym.getAddress(); 37 default: 38 return Sym.getAddress(); 39 } 40 } 41 42 } // end anonymous namespace 43 44 namespace llvm { 45 namespace orc { 46 47 class LinkGraphLinkingLayer::JITLinkCtx final : public JITLinkContext { 48 public: 49 JITLinkCtx(LinkGraphLinkingLayer &Layer, 50 std::unique_ptr<MaterializationResponsibility> MR, 51 std::unique_ptr<MemoryBuffer> ObjBuffer) 52 : JITLinkContext(&MR->getTargetJITDylib()), Layer(Layer), 53 MR(std::move(MR)), ObjBuffer(std::move(ObjBuffer)) { 54 std::lock_guard<std::mutex> Lock(Layer.LayerMutex); 55 Plugins = Layer.Plugins; 56 } 57 58 ~JITLinkCtx() { 59 // If there is an object buffer return function then use it to 60 // return ownership of the buffer. 61 if (Layer.ReturnObjectBuffer && ObjBuffer) 62 Layer.ReturnObjectBuffer(std::move(ObjBuffer)); 63 } 64 65 JITLinkMemoryManager &getMemoryManager() override { return Layer.MemMgr; } 66 67 void notifyMaterializing(LinkGraph &G) { 68 for (auto &P : Plugins) 69 P->notifyMaterializing(*MR, G, *this, 70 ObjBuffer ? ObjBuffer->getMemBufferRef() 71 : MemoryBufferRef()); 72 } 73 74 void notifyFailed(Error Err) override { 75 for (auto &P : Plugins) 76 Err = joinErrors(std::move(Err), P->notifyFailed(*MR)); 77 Layer.getExecutionSession().reportError(std::move(Err)); 78 MR->failMaterialization(); 79 } 80 81 void lookup(const LookupMap &Symbols, 82 std::unique_ptr<JITLinkAsyncLookupContinuation> LC) override { 83 84 JITDylibSearchOrder LinkOrder; 85 MR->getTargetJITDylib().withLinkOrderDo( 86 [&](const JITDylibSearchOrder &LO) { LinkOrder = LO; }); 87 88 auto &ES = Layer.getExecutionSession(); 89 90 SymbolLookupSet LookupSet; 91 for (auto &KV : Symbols) { 92 orc::SymbolLookupFlags LookupFlags; 93 switch (KV.second) { 94 case jitlink::SymbolLookupFlags::RequiredSymbol: 95 LookupFlags = orc::SymbolLookupFlags::RequiredSymbol; 96 break; 97 case jitlink::SymbolLookupFlags::WeaklyReferencedSymbol: 98 LookupFlags = orc::SymbolLookupFlags::WeaklyReferencedSymbol; 99 break; 100 } 101 LookupSet.add(KV.first, LookupFlags); 102 } 103 104 // OnResolve -- De-intern the symbols and pass the result to the linker. 105 auto OnResolve = [LookupContinuation = 106 std::move(LC)](Expected<SymbolMap> Result) mutable { 107 if (!Result) 108 LookupContinuation->run(Result.takeError()); 109 else { 110 AsyncLookupResult LR; 111 LR.insert_range(*Result); 112 LookupContinuation->run(std::move(LR)); 113 } 114 }; 115 116 ES.lookup(LookupKind::Static, LinkOrder, std::move(LookupSet), 117 SymbolState::Resolved, std::move(OnResolve), 118 [this](const SymbolDependenceMap &Deps) { 119 // Translate LookupDeps map to SymbolSourceJD. 120 for (auto &[DepJD, Deps] : Deps) 121 for (auto &DepSym : Deps) 122 SymbolSourceJDs[NonOwningSymbolStringPtr(DepSym)] = DepJD; 123 }); 124 } 125 126 Error notifyResolved(LinkGraph &G) override { 127 128 SymbolFlagsMap ExtraSymbolsToClaim; 129 bool AutoClaim = Layer.AutoClaimObjectSymbols; 130 131 SymbolMap InternedResult; 132 for (auto *Sym : G.defined_symbols()) 133 if (Sym->getScope() < Scope::SideEffectsOnly) { 134 auto Ptr = getJITSymbolPtrForSymbol(*Sym, G.getTargetTriple()); 135 auto Flags = getJITSymbolFlagsForSymbol(*Sym); 136 InternedResult[Sym->getName()] = {Ptr, Flags}; 137 if (AutoClaim && !MR->getSymbols().count(Sym->getName())) { 138 assert(!ExtraSymbolsToClaim.count(Sym->getName()) && 139 "Duplicate symbol to claim?"); 140 ExtraSymbolsToClaim[Sym->getName()] = Flags; 141 } 142 } 143 144 for (auto *Sym : G.absolute_symbols()) 145 if (Sym->getScope() < Scope::SideEffectsOnly) { 146 auto Ptr = getJITSymbolPtrForSymbol(*Sym, G.getTargetTriple()); 147 auto Flags = getJITSymbolFlagsForSymbol(*Sym); 148 InternedResult[Sym->getName()] = {Ptr, Flags}; 149 if (AutoClaim && !MR->getSymbols().count(Sym->getName())) { 150 assert(!ExtraSymbolsToClaim.count(Sym->getName()) && 151 "Duplicate symbol to claim?"); 152 ExtraSymbolsToClaim[Sym->getName()] = Flags; 153 } 154 } 155 156 if (!ExtraSymbolsToClaim.empty()) 157 if (auto Err = MR->defineMaterializing(ExtraSymbolsToClaim)) 158 return Err; 159 160 { 161 162 // Check that InternedResult matches up with MR->getSymbols(), overriding 163 // flags if requested. 164 // This guards against faulty transformations / compilers / object caches. 165 166 // First check that there aren't any missing symbols. 167 size_t NumMaterializationSideEffectsOnlySymbols = 0; 168 SymbolNameVector MissingSymbols; 169 for (auto &[Sym, Flags] : MR->getSymbols()) { 170 171 auto I = InternedResult.find(Sym); 172 173 // If this is a materialization-side-effects only symbol then bump 174 // the counter and remove in from the result, otherwise make sure that 175 // it's defined. 176 if (Flags.hasMaterializationSideEffectsOnly()) 177 ++NumMaterializationSideEffectsOnlySymbols; 178 else if (I == InternedResult.end()) 179 MissingSymbols.push_back(Sym); 180 else if (Layer.OverrideObjectFlags) 181 I->second.setFlags(Flags); 182 } 183 184 // If there were missing symbols then report the error. 185 if (!MissingSymbols.empty()) 186 return make_error<MissingSymbolDefinitions>( 187 Layer.getExecutionSession().getSymbolStringPool(), G.getName(), 188 std::move(MissingSymbols)); 189 190 // If there are more definitions than expected, add them to the 191 // ExtraSymbols vector. 192 SymbolNameVector ExtraSymbols; 193 if (InternedResult.size() > 194 MR->getSymbols().size() - NumMaterializationSideEffectsOnlySymbols) { 195 for (auto &KV : InternedResult) 196 if (!MR->getSymbols().count(KV.first)) 197 ExtraSymbols.push_back(KV.first); 198 } 199 200 // If there were extra definitions then report the error. 201 if (!ExtraSymbols.empty()) 202 return make_error<UnexpectedSymbolDefinitions>( 203 Layer.getExecutionSession().getSymbolStringPool(), G.getName(), 204 std::move(ExtraSymbols)); 205 } 206 207 if (auto Err = MR->notifyResolved(InternedResult)) 208 return Err; 209 210 return Error::success(); 211 } 212 213 void notifyFinalized(JITLinkMemoryManager::FinalizedAlloc A) override { 214 if (auto Err = notifyEmitted(std::move(A))) { 215 Layer.getExecutionSession().reportError(std::move(Err)); 216 MR->failMaterialization(); 217 return; 218 } 219 220 if (auto Err = MR->notifyEmitted(SymbolDepGroups)) { 221 Layer.getExecutionSession().reportError(std::move(Err)); 222 MR->failMaterialization(); 223 } 224 } 225 226 LinkGraphPassFunction getMarkLivePass(const Triple &TT) const override { 227 return [this](LinkGraph &G) { return markResponsibilitySymbolsLive(G); }; 228 } 229 230 Error modifyPassConfig(LinkGraph &LG, PassConfiguration &Config) override { 231 // Add passes to mark duplicate defs as should-discard, and to walk the 232 // link graph to build the symbol dependence graph. 233 Config.PrePrunePasses.push_back([this](LinkGraph &G) { 234 return claimOrExternalizeWeakAndCommonSymbols(G); 235 }); 236 237 for (auto &P : Plugins) 238 P->modifyPassConfig(*MR, LG, Config); 239 240 Config.PreFixupPasses.push_back( 241 [this](LinkGraph &G) { return registerDependencies(G); }); 242 243 return Error::success(); 244 } 245 246 Error notifyEmitted(jitlink::JITLinkMemoryManager::FinalizedAlloc FA) { 247 Error Err = Error::success(); 248 for (auto &P : Plugins) 249 Err = joinErrors(std::move(Err), P->notifyEmitted(*MR)); 250 251 if (Err) { 252 if (FA) 253 Err = 254 joinErrors(std::move(Err), Layer.MemMgr.deallocate(std::move(FA))); 255 return Err; 256 } 257 258 if (FA) 259 return Layer.recordFinalizedAlloc(*MR, std::move(FA)); 260 261 return Error::success(); 262 } 263 264 private: 265 Error claimOrExternalizeWeakAndCommonSymbols(LinkGraph &G) { 266 SymbolFlagsMap NewSymbolsToClaim; 267 std::vector<std::pair<SymbolStringPtr, Symbol *>> NameToSym; 268 269 auto ProcessSymbol = [&](Symbol *Sym) { 270 if (Sym->hasName() && Sym->getLinkage() == Linkage::Weak && 271 Sym->getScope() != Scope::Local) { 272 if (!MR->getSymbols().count(Sym->getName())) { 273 NewSymbolsToClaim[Sym->getName()] = 274 getJITSymbolFlagsForSymbol(*Sym) | JITSymbolFlags::Weak; 275 NameToSym.push_back(std::make_pair(Sym->getName(), Sym)); 276 } 277 } 278 }; 279 280 for (auto *Sym : G.defined_symbols()) 281 ProcessSymbol(Sym); 282 for (auto *Sym : G.absolute_symbols()) 283 ProcessSymbol(Sym); 284 285 // Attempt to claim all weak defs that we're not already responsible for. 286 // This may fail if the resource tracker has become defunct, but should 287 // always succeed otherwise. 288 if (auto Err = MR->defineMaterializing(std::move(NewSymbolsToClaim))) 289 return Err; 290 291 // Walk the list of symbols that we just tried to claim. Symbols that we're 292 // responsible for are marked live. Symbols that we're not responsible for 293 // are turned into external references. 294 for (auto &KV : NameToSym) { 295 if (MR->getSymbols().count(KV.first)) 296 KV.second->setLive(true); 297 else 298 G.makeExternal(*KV.second); 299 } 300 301 return Error::success(); 302 } 303 304 Error markResponsibilitySymbolsLive(LinkGraph &G) const { 305 for (auto *Sym : G.defined_symbols()) 306 if (Sym->hasName() && MR->getSymbols().count(Sym->getName())) 307 Sym->setLive(true); 308 return Error::success(); 309 } 310 311 Error registerDependencies(LinkGraph &G) { 312 313 struct BlockInfo { 314 bool InWorklist = false; 315 DenseSet<Symbol *> Defs; 316 DenseSet<Symbol *> SymbolDeps; 317 DenseSet<Block *> AnonEdges, AnonBackEdges; 318 }; 319 320 DenseMap<Block *, BlockInfo> BlockInfos; 321 322 // Reserve space so that BlockInfos doesn't need to resize. This is 323 // essential to avoid invalidating pointers to entries below. 324 { 325 size_t NumBlocks = 0; 326 for (auto &Sec : G.sections()) 327 NumBlocks += Sec.blocks_size(); 328 BlockInfos.reserve(NumBlocks); 329 } 330 331 // Identify non-locally-scoped symbols defined by each block. 332 for (auto *Sym : G.defined_symbols()) { 333 if (Sym->getScope() != Scope::Local) 334 BlockInfos[&Sym->getBlock()].Defs.insert(Sym); 335 } 336 337 // Identify the symbolic and anonymous-block dependencies for each block. 338 for (auto *B : G.blocks()) { 339 auto &BI = BlockInfos[B]; 340 341 for (auto &E : B->edges()) { 342 343 // External symbols are trivially depended on. 344 if (E.getTarget().isExternal()) { 345 BI.SymbolDeps.insert(&E.getTarget()); 346 continue; 347 } 348 349 // Anonymous symbols aren't depended on at all (they're assumed to be 350 // already available). 351 if (E.getTarget().isAbsolute()) 352 continue; 353 354 // If we get here then we depend on a symbol defined by some other 355 // block. 356 auto &TgtBI = BlockInfos[&E.getTarget().getBlock()]; 357 358 // If that block has any definitions then use the first one as the 359 // "effective" dependence here (all symbols in TgtBI will become 360 // ready at the same time, and chosing a single symbol to represent 361 // the block keeps the SymbolDepGroup size small). 362 if (!TgtBI.Defs.empty()) { 363 BI.SymbolDeps.insert(*TgtBI.Defs.begin()); 364 continue; 365 } 366 367 // Otherwise we've got a dependence on an anonymous block. Record it 368 // here for back-propagating symbol dependencies below. 369 BI.AnonEdges.insert(&E.getTarget().getBlock()); 370 TgtBI.AnonBackEdges.insert(B); 371 } 372 } 373 374 // Prune anonymous blocks. 375 { 376 std::vector<Block *> BlocksToRemove; 377 for (auto &[B, BI] : BlockInfos) { 378 // Skip blocks with defs. We only care about anonyous blocks. 379 if (!BI.Defs.empty()) 380 continue; 381 382 BlocksToRemove.push_back(B); 383 384 for (auto *FB : BI.AnonEdges) 385 BlockInfos[FB].AnonBackEdges.erase(B); 386 387 for (auto *BB : BI.AnonBackEdges) 388 BlockInfos[BB].AnonEdges.erase(B); 389 390 for (auto *FB : BI.AnonEdges) { 391 auto &FBI = BlockInfos[FB]; 392 FBI.AnonBackEdges.insert_range(BI.AnonBackEdges); 393 } 394 395 for (auto *BB : BI.AnonBackEdges) { 396 auto &BBI = BlockInfos[BB]; 397 BBI.SymbolDeps.insert_range(BI.SymbolDeps); 398 BBI.AnonEdges.insert_range(BI.AnonEdges); 399 } 400 } 401 402 for (auto *B : BlocksToRemove) 403 BlockInfos.erase(B); 404 } 405 406 // Build the initial dependence propagation worklist. 407 std::deque<Block *> Worklist; 408 for (auto &[B, BI] : BlockInfos) { 409 if (!BI.SymbolDeps.empty() && !BI.AnonBackEdges.empty()) { 410 Worklist.push_back(B); 411 BI.InWorklist = true; 412 } 413 } 414 415 // Propagate symbol deps through the graph. 416 while (!Worklist.empty()) { 417 auto *B = Worklist.front(); 418 Worklist.pop_front(); 419 420 auto &BI = BlockInfos[B]; 421 BI.InWorklist = false; 422 423 for (auto *DB : BI.AnonBackEdges) { 424 auto &DBI = BlockInfos[DB]; 425 for (auto *Sym : BI.SymbolDeps) { 426 if (DBI.SymbolDeps.insert(Sym).second && !DBI.InWorklist) { 427 Worklist.push_back(DB); 428 DBI.InWorklist = true; 429 } 430 } 431 } 432 } 433 434 // Transform our local dependence information into a list of 435 // SymbolDependenceGroups (in the SymbolDepGroups member), ready for use in 436 // the upcoming notifyFinalized call. 437 auto &TargetJD = MR->getTargetJITDylib(); 438 439 for (auto &[B, BI] : BlockInfos) { 440 if (!BI.Defs.empty()) { 441 SymbolDepGroups.push_back(SymbolDependenceGroup()); 442 auto &SDG = SymbolDepGroups.back(); 443 444 for (auto *Def : BI.Defs) 445 SDG.Symbols.insert(Def->getName()); 446 447 for (auto *Dep : BI.SymbolDeps) { 448 auto DepName = Dep->getName(); 449 if (Dep->isDefined()) 450 SDG.Dependencies[&TargetJD].insert(std::move(DepName)); 451 else { 452 auto SourceJDItr = 453 SymbolSourceJDs.find(NonOwningSymbolStringPtr(DepName)); 454 if (SourceJDItr != SymbolSourceJDs.end()) 455 SDG.Dependencies[SourceJDItr->second].insert(std::move(DepName)); 456 } 457 } 458 } 459 } 460 461 return Error::success(); 462 } 463 464 LinkGraphLinkingLayer &Layer; 465 std::vector<std::shared_ptr<LinkGraphLinkingLayer::Plugin>> Plugins; 466 std::unique_ptr<MaterializationResponsibility> MR; 467 std::unique_ptr<MemoryBuffer> ObjBuffer; 468 DenseMap<NonOwningSymbolStringPtr, JITDylib *> SymbolSourceJDs; 469 std::vector<SymbolDependenceGroup> SymbolDepGroups; 470 }; 471 472 LinkGraphLinkingLayer::Plugin::~Plugin() = default; 473 474 LinkGraphLinkingLayer::LinkGraphLinkingLayer(ExecutionSession &ES) 475 : LinkGraphLayer(ES), MemMgr(ES.getExecutorProcessControl().getMemMgr()) { 476 ES.registerResourceManager(*this); 477 } 478 479 LinkGraphLinkingLayer::LinkGraphLinkingLayer(ExecutionSession &ES, 480 JITLinkMemoryManager &MemMgr) 481 : LinkGraphLayer(ES), MemMgr(MemMgr) { 482 ES.registerResourceManager(*this); 483 } 484 485 LinkGraphLinkingLayer::LinkGraphLinkingLayer( 486 ExecutionSession &ES, std::unique_ptr<JITLinkMemoryManager> MemMgr) 487 : LinkGraphLayer(ES), MemMgr(*MemMgr), MemMgrOwnership(std::move(MemMgr)) { 488 ES.registerResourceManager(*this); 489 } 490 491 LinkGraphLinkingLayer::~LinkGraphLinkingLayer() { 492 assert(Allocs.empty() && 493 "Layer destroyed with resources still attached " 494 "(ExecutionSession::endSession() must be called prior to " 495 "destruction)"); 496 getExecutionSession().deregisterResourceManager(*this); 497 } 498 499 void LinkGraphLinkingLayer::emit( 500 std::unique_ptr<MaterializationResponsibility> R, 501 std::unique_ptr<LinkGraph> G) { 502 assert(R && "R must not be null"); 503 assert(G && "G must not be null"); 504 auto Ctx = std::make_unique<JITLinkCtx>(*this, std::move(R), nullptr); 505 Ctx->notifyMaterializing(*G); 506 link(std::move(G), std::move(Ctx)); 507 } 508 509 void LinkGraphLinkingLayer::emit( 510 std::unique_ptr<MaterializationResponsibility> R, 511 std::unique_ptr<LinkGraph> G, std::unique_ptr<MemoryBuffer> ObjBuf) { 512 assert(R && "R must not be null"); 513 assert(G && "G must not be null"); 514 assert(ObjBuf && "Object must not be null"); 515 auto Ctx = 516 std::make_unique<JITLinkCtx>(*this, std::move(R), std::move(ObjBuf)); 517 Ctx->notifyMaterializing(*G); 518 link(std::move(G), std::move(Ctx)); 519 } 520 521 Error LinkGraphLinkingLayer::recordFinalizedAlloc( 522 MaterializationResponsibility &MR, FinalizedAlloc FA) { 523 auto Err = MR.withResourceKeyDo( 524 [&](ResourceKey K) { Allocs[K].push_back(std::move(FA)); }); 525 526 if (Err) 527 Err = joinErrors(std::move(Err), MemMgr.deallocate(std::move(FA))); 528 529 return Err; 530 } 531 532 Error LinkGraphLinkingLayer::handleRemoveResources(JITDylib &JD, 533 ResourceKey K) { 534 535 { 536 Error Err = Error::success(); 537 for (auto &P : Plugins) 538 Err = joinErrors(std::move(Err), P->notifyRemovingResources(JD, K)); 539 if (Err) 540 return Err; 541 } 542 543 std::vector<FinalizedAlloc> AllocsToRemove; 544 getExecutionSession().runSessionLocked([&] { 545 auto I = Allocs.find(K); 546 if (I != Allocs.end()) { 547 std::swap(AllocsToRemove, I->second); 548 Allocs.erase(I); 549 } 550 }); 551 552 if (AllocsToRemove.empty()) 553 return Error::success(); 554 555 return MemMgr.deallocate(std::move(AllocsToRemove)); 556 } 557 558 void LinkGraphLinkingLayer::handleTransferResources(JITDylib &JD, 559 ResourceKey DstKey, 560 ResourceKey SrcKey) { 561 if (Allocs.contains(SrcKey)) { 562 // DstKey may not be in the DenseMap yet, so the following line may resize 563 // the container and invalidate iterators and value references. 564 auto &DstAllocs = Allocs[DstKey]; 565 auto &SrcAllocs = Allocs[SrcKey]; 566 DstAllocs.reserve(DstAllocs.size() + SrcAllocs.size()); 567 for (auto &Alloc : SrcAllocs) 568 DstAllocs.push_back(std::move(Alloc)); 569 570 Allocs.erase(SrcKey); 571 } 572 573 for (auto &P : Plugins) 574 P->notifyTransferringResources(JD, DstKey, SrcKey); 575 } 576 577 } // End namespace orc. 578 } // End namespace llvm. 579