1 //===--------- JITLinkGeneric.cpp - Generic JIT linker utilities ----------===// 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 // Generic JITLinker utility class. 10 // 11 //===----------------------------------------------------------------------===// 12 13 #include "JITLinkGeneric.h" 14 15 #include "llvm/Support/BinaryStreamReader.h" 16 #include "llvm/Support/MemoryBuffer.h" 17 18 #define DEBUG_TYPE "jitlink" 19 20 namespace llvm { 21 namespace jitlink { 22 23 JITLinkerBase::~JITLinkerBase() {} 24 25 void JITLinkerBase::linkPhase1(std::unique_ptr<JITLinkerBase> Self) { 26 27 LLVM_DEBUG({ 28 dbgs() << "Starting link phase 1 for graph " << G->getName() << "\n"; 29 }); 30 31 // Prune and optimize the graph. 32 if (auto Err = runPasses(Passes.PrePrunePasses)) 33 return Ctx->notifyFailed(std::move(Err)); 34 35 LLVM_DEBUG({ 36 dbgs() << "Link graph \"" << G->getName() << "\" pre-pruning:\n"; 37 dumpGraph(dbgs()); 38 }); 39 40 prune(*G); 41 42 LLVM_DEBUG({ 43 dbgs() << "Link graph \"" << G->getName() << "\" post-pruning:\n"; 44 dumpGraph(dbgs()); 45 }); 46 47 // Run post-pruning passes. 48 if (auto Err = runPasses(Passes.PostPrunePasses)) 49 return Ctx->notifyFailed(std::move(Err)); 50 51 // Sort blocks into segments. 52 auto Layout = layOutBlocks(); 53 54 // Allocate memory for segments. 55 if (auto Err = allocateSegments(Layout)) 56 return Ctx->notifyFailed(std::move(Err)); 57 58 // Notify client that the defined symbols have been assigned addresses. 59 LLVM_DEBUG( 60 { dbgs() << "Resolving symbols defined in " << G->getName() << "\n"; }); 61 62 if (auto Err = Ctx->notifyResolved(*G)) 63 return Ctx->notifyFailed(std::move(Err)); 64 65 auto ExternalSymbols = getExternalSymbolNames(); 66 67 LLVM_DEBUG({ 68 dbgs() << "Issuing lookup for external symbols for " << G->getName() 69 << " (may trigger materialization/linking of other graphs)...\n"; 70 }); 71 72 // We're about to hand off ownership of ourself to the continuation. Grab a 73 // pointer to the context so that we can call it to initiate the lookup. 74 // 75 // FIXME: Once callee expressions are defined to be sequenced before argument 76 // expressions (c++17) we can simplify all this to: 77 // 78 // Ctx->lookup(std::move(UnresolvedExternals), 79 // [Self=std::move(Self)](Expected<AsyncLookupResult> Result) { 80 // Self->linkPhase2(std::move(Self), std::move(Result)); 81 // }); 82 auto *TmpCtx = Ctx.get(); 83 TmpCtx->lookup(std::move(ExternalSymbols), 84 createLookupContinuation( 85 [S = std::move(Self), L = std::move(Layout)]( 86 Expected<AsyncLookupResult> LookupResult) mutable { 87 auto &TmpSelf = *S; 88 TmpSelf.linkPhase2(std::move(S), std::move(LookupResult), 89 std::move(L)); 90 })); 91 } 92 93 void JITLinkerBase::linkPhase2(std::unique_ptr<JITLinkerBase> Self, 94 Expected<AsyncLookupResult> LR, 95 SegmentLayoutMap Layout) { 96 97 LLVM_DEBUG({ 98 dbgs() << "Starting link phase 2 for graph " << G->getName() << "\n"; 99 }); 100 101 // If the lookup failed, bail out. 102 if (!LR) 103 return deallocateAndBailOut(LR.takeError()); 104 105 // Assign addresses to external addressables. 106 applyLookupResult(*LR); 107 108 // Copy block content to working memory. 109 copyBlockContentToWorkingMemory(Layout, *Alloc); 110 111 LLVM_DEBUG({ 112 dbgs() << "Link graph \"" << G->getName() 113 << "\" before post-allocation passes:\n"; 114 dumpGraph(dbgs()); 115 }); 116 117 if (auto Err = runPasses(Passes.PostAllocationPasses)) 118 return deallocateAndBailOut(std::move(Err)); 119 120 LLVM_DEBUG({ 121 dbgs() << "Link graph \"" << G->getName() << "\" before copy-and-fixup:\n"; 122 dumpGraph(dbgs()); 123 }); 124 125 // Fix up block content. 126 if (auto Err = fixUpBlocks(*G)) 127 return deallocateAndBailOut(std::move(Err)); 128 129 LLVM_DEBUG({ 130 dbgs() << "Link graph \"" << G->getName() << "\" after copy-and-fixup:\n"; 131 dumpGraph(dbgs()); 132 }); 133 134 if (auto Err = runPasses(Passes.PostFixupPasses)) 135 return deallocateAndBailOut(std::move(Err)); 136 137 // FIXME: Use move capture once we have c++14. 138 auto *UnownedSelf = Self.release(); 139 auto Phase3Continuation = [UnownedSelf](Error Err) { 140 std::unique_ptr<JITLinkerBase> Self(UnownedSelf); 141 UnownedSelf->linkPhase3(std::move(Self), std::move(Err)); 142 }; 143 144 Alloc->finalizeAsync(std::move(Phase3Continuation)); 145 } 146 147 void JITLinkerBase::linkPhase3(std::unique_ptr<JITLinkerBase> Self, Error Err) { 148 149 LLVM_DEBUG({ 150 dbgs() << "Starting link phase 3 for graph " << G->getName() << "\n"; 151 }); 152 153 if (Err) 154 return deallocateAndBailOut(std::move(Err)); 155 Ctx->notifyFinalized(std::move(Alloc)); 156 157 LLVM_DEBUG({ dbgs() << "Link of graph " << G->getName() << " complete\n"; }); 158 } 159 160 Error JITLinkerBase::runPasses(LinkGraphPassList &Passes) { 161 for (auto &P : Passes) 162 if (auto Err = P(*G)) 163 return Err; 164 return Error::success(); 165 } 166 167 JITLinkerBase::SegmentLayoutMap JITLinkerBase::layOutBlocks() { 168 169 SegmentLayoutMap Layout; 170 171 /// Partition blocks based on permissions and content vs. zero-fill. 172 for (auto *B : G->blocks()) { 173 auto &SegLists = Layout[B->getSection().getProtectionFlags()]; 174 if (!B->isZeroFill()) 175 SegLists.ContentBlocks.push_back(B); 176 else 177 SegLists.ZeroFillBlocks.push_back(B); 178 } 179 180 /// Sort blocks within each list. 181 for (auto &KV : Layout) { 182 183 auto CompareBlocks = [](const Block *LHS, const Block *RHS) { 184 // Sort by section, address and size 185 if (LHS->getSection().getOrdinal() != RHS->getSection().getOrdinal()) 186 return LHS->getSection().getOrdinal() < RHS->getSection().getOrdinal(); 187 if (LHS->getAddress() != RHS->getAddress()) 188 return LHS->getAddress() < RHS->getAddress(); 189 return LHS->getSize() < RHS->getSize(); 190 }; 191 192 auto &SegLists = KV.second; 193 llvm::sort(SegLists.ContentBlocks, CompareBlocks); 194 llvm::sort(SegLists.ZeroFillBlocks, CompareBlocks); 195 } 196 197 LLVM_DEBUG({ 198 dbgs() << "Computed segment ordering:\n"; 199 for (auto &KV : Layout) { 200 dbgs() << " Segment " 201 << static_cast<sys::Memory::ProtectionFlags>(KV.first) << ":\n"; 202 auto &SL = KV.second; 203 for (auto &SIEntry : 204 {std::make_pair(&SL.ContentBlocks, "content block"), 205 std::make_pair(&SL.ZeroFillBlocks, "zero-fill block")}) { 206 dbgs() << " " << SIEntry.second << ":\n"; 207 for (auto *B : *SIEntry.first) 208 dbgs() << " " << *B << "\n"; 209 } 210 } 211 }); 212 213 return Layout; 214 } 215 216 Error JITLinkerBase::allocateSegments(const SegmentLayoutMap &Layout) { 217 218 // Compute segment sizes and allocate memory. 219 LLVM_DEBUG(dbgs() << "JIT linker requesting: { "); 220 JITLinkMemoryManager::SegmentsRequestMap Segments; 221 for (auto &KV : Layout) { 222 auto &Prot = KV.first; 223 auto &SegLists = KV.second; 224 225 uint64_t SegAlign = 1; 226 227 // Calculate segment content size. 228 size_t SegContentSize = 0; 229 for (auto *B : SegLists.ContentBlocks) { 230 SegAlign = std::max(SegAlign, B->getAlignment()); 231 SegContentSize = alignToBlock(SegContentSize, *B); 232 SegContentSize += B->getSize(); 233 } 234 235 uint64_t SegZeroFillStart = SegContentSize; 236 uint64_t SegZeroFillEnd = SegZeroFillStart; 237 238 for (auto *B : SegLists.ZeroFillBlocks) { 239 SegAlign = std::max(SegAlign, B->getAlignment()); 240 SegZeroFillEnd = alignToBlock(SegZeroFillEnd, *B); 241 SegZeroFillEnd += B->getSize(); 242 } 243 244 Segments[Prot] = {SegAlign, SegContentSize, 245 SegZeroFillEnd - SegZeroFillStart}; 246 247 LLVM_DEBUG({ 248 dbgs() << (&KV == &*Layout.begin() ? "" : "; ") 249 << static_cast<sys::Memory::ProtectionFlags>(Prot) 250 << ": alignment = " << SegAlign 251 << ", content size = " << SegContentSize 252 << ", zero-fill size = " << (SegZeroFillEnd - SegZeroFillStart); 253 }); 254 } 255 LLVM_DEBUG(dbgs() << " }\n"); 256 257 if (auto AllocOrErr = 258 Ctx->getMemoryManager().allocate(Ctx->getJITLinkDylib(), Segments)) 259 Alloc = std::move(*AllocOrErr); 260 else 261 return AllocOrErr.takeError(); 262 263 LLVM_DEBUG({ 264 dbgs() << "JIT linker got memory (working -> target):\n"; 265 for (auto &KV : Layout) { 266 auto Prot = static_cast<sys::Memory::ProtectionFlags>(KV.first); 267 dbgs() << " " << Prot << ": " 268 << (const void *)Alloc->getWorkingMemory(Prot).data() << " -> " 269 << formatv("{0:x16}", Alloc->getTargetMemory(Prot)) << "\n"; 270 } 271 }); 272 273 // Update block target addresses. 274 for (auto &KV : Layout) { 275 auto &Prot = KV.first; 276 auto &SL = KV.second; 277 278 JITTargetAddress NextBlockAddr = 279 Alloc->getTargetMemory(static_cast<sys::Memory::ProtectionFlags>(Prot)); 280 281 for (auto *SIList : {&SL.ContentBlocks, &SL.ZeroFillBlocks}) 282 for (auto *B : *SIList) { 283 NextBlockAddr = alignToBlock(NextBlockAddr, *B); 284 B->setAddress(NextBlockAddr); 285 NextBlockAddr += B->getSize(); 286 } 287 } 288 289 return Error::success(); 290 } 291 292 JITLinkContext::LookupMap JITLinkerBase::getExternalSymbolNames() const { 293 // Identify unresolved external symbols. 294 JITLinkContext::LookupMap UnresolvedExternals; 295 for (auto *Sym : G->external_symbols()) { 296 assert(Sym->getAddress() == 0 && 297 "External has already been assigned an address"); 298 assert(Sym->getName() != StringRef() && Sym->getName() != "" && 299 "Externals must be named"); 300 SymbolLookupFlags LookupFlags = 301 Sym->getLinkage() == Linkage::Weak 302 ? SymbolLookupFlags::WeaklyReferencedSymbol 303 : SymbolLookupFlags::RequiredSymbol; 304 UnresolvedExternals[Sym->getName()] = LookupFlags; 305 } 306 return UnresolvedExternals; 307 } 308 309 void JITLinkerBase::applyLookupResult(AsyncLookupResult Result) { 310 for (auto *Sym : G->external_symbols()) { 311 assert(Sym->getOffset() == 0 && 312 "External symbol is not at the start of its addressable block"); 313 assert(Sym->getAddress() == 0 && "Symbol already resolved"); 314 assert(!Sym->isDefined() && "Symbol being resolved is already defined"); 315 auto ResultI = Result.find(Sym->getName()); 316 if (ResultI != Result.end()) 317 Sym->getAddressable().setAddress(ResultI->second.getAddress()); 318 else 319 assert(Sym->getLinkage() == Linkage::Weak && 320 "Failed to resolve non-weak reference"); 321 } 322 323 LLVM_DEBUG({ 324 dbgs() << "Externals after applying lookup result:\n"; 325 for (auto *Sym : G->external_symbols()) 326 dbgs() << " " << Sym->getName() << ": " 327 << formatv("{0:x16}", Sym->getAddress()) << "\n"; 328 }); 329 } 330 331 void JITLinkerBase::copyBlockContentToWorkingMemory( 332 const SegmentLayoutMap &Layout, JITLinkMemoryManager::Allocation &Alloc) { 333 334 LLVM_DEBUG(dbgs() << "Copying block content:\n"); 335 for (auto &KV : Layout) { 336 auto &Prot = KV.first; 337 auto &SegLayout = KV.second; 338 339 auto SegMem = 340 Alloc.getWorkingMemory(static_cast<sys::Memory::ProtectionFlags>(Prot)); 341 char *LastBlockEnd = SegMem.data(); 342 char *BlockDataPtr = LastBlockEnd; 343 344 LLVM_DEBUG({ 345 dbgs() << " Processing segment " 346 << static_cast<sys::Memory::ProtectionFlags>(Prot) << " [ " 347 << (const void *)SegMem.data() << " .. " 348 << (const void *)((char *)SegMem.data() + SegMem.size()) 349 << " ]\n Processing content sections:\n"; 350 }); 351 352 for (auto *B : SegLayout.ContentBlocks) { 353 LLVM_DEBUG(dbgs() << " " << *B << ":\n"); 354 355 // Pad to alignment/alignment-offset. 356 BlockDataPtr = alignToBlock(BlockDataPtr, *B); 357 358 LLVM_DEBUG({ 359 dbgs() << " Bumped block pointer to " << (const void *)BlockDataPtr 360 << " to meet block alignment " << B->getAlignment() 361 << " and alignment offset " << B->getAlignmentOffset() << "\n"; 362 }); 363 364 // Zero pad up to alignment. 365 LLVM_DEBUG({ 366 if (LastBlockEnd != BlockDataPtr) 367 dbgs() << " Zero padding from " << (const void *)LastBlockEnd 368 << " to " << (const void *)BlockDataPtr << "\n"; 369 }); 370 371 while (LastBlockEnd != BlockDataPtr) 372 *LastBlockEnd++ = 0; 373 374 // Copy initial block content. 375 LLVM_DEBUG({ 376 dbgs() << " Copying block " << *B << " content, " 377 << B->getContent().size() << " bytes, from " 378 << (const void *)B->getContent().data() << " to " 379 << (const void *)BlockDataPtr << "\n"; 380 }); 381 memcpy(BlockDataPtr, B->getContent().data(), B->getContent().size()); 382 383 // Point the block's content to the fixed up buffer. 384 B->setContent(StringRef(BlockDataPtr, B->getContent().size())); 385 386 // Update block end pointer. 387 LastBlockEnd = BlockDataPtr + B->getContent().size(); 388 BlockDataPtr = LastBlockEnd; 389 } 390 391 // Zero pad the rest of the segment. 392 LLVM_DEBUG({ 393 dbgs() << " Zero padding end of segment from " 394 << (const void *)LastBlockEnd << " to " 395 << (const void *)((char *)SegMem.data() + SegMem.size()) << "\n"; 396 }); 397 while (LastBlockEnd != SegMem.data() + SegMem.size()) 398 *LastBlockEnd++ = 0; 399 } 400 } 401 402 void JITLinkerBase::deallocateAndBailOut(Error Err) { 403 assert(Err && "Should not be bailing out on success value"); 404 assert(Alloc && "can not call deallocateAndBailOut before allocation"); 405 Ctx->notifyFailed(joinErrors(std::move(Err), Alloc->deallocate())); 406 } 407 408 void JITLinkerBase::dumpGraph(raw_ostream &OS) { 409 assert(G && "Graph is not set yet"); 410 G->dump(dbgs(), [this](Edge::Kind K) { return getEdgeKindName(K); }); 411 } 412 413 void prune(LinkGraph &G) { 414 std::vector<Symbol *> Worklist; 415 DenseSet<Block *> VisitedBlocks; 416 417 // Build the initial worklist from all symbols initially live. 418 for (auto *Sym : G.defined_symbols()) 419 if (Sym->isLive()) 420 Worklist.push_back(Sym); 421 422 // Propagate live flags to all symbols reachable from the initial live set. 423 while (!Worklist.empty()) { 424 auto *Sym = Worklist.back(); 425 Worklist.pop_back(); 426 427 auto &B = Sym->getBlock(); 428 429 // Skip addressables that we've visited before. 430 if (VisitedBlocks.count(&B)) 431 continue; 432 433 VisitedBlocks.insert(&B); 434 435 for (auto &E : Sym->getBlock().edges()) { 436 // If the edge target is a defined symbol that is being newly marked live 437 // then add it to the worklist. 438 if (E.getTarget().isDefined() && !E.getTarget().isLive()) 439 Worklist.push_back(&E.getTarget()); 440 441 // Mark the target live. 442 E.getTarget().setLive(true); 443 } 444 } 445 446 // Collect all defined symbols to remove, then remove them. 447 { 448 LLVM_DEBUG(dbgs() << "Dead-stripping defined symbols:\n"); 449 std::vector<Symbol *> SymbolsToRemove; 450 for (auto *Sym : G.defined_symbols()) 451 if (!Sym->isLive()) 452 SymbolsToRemove.push_back(Sym); 453 for (auto *Sym : SymbolsToRemove) { 454 LLVM_DEBUG(dbgs() << " " << *Sym << "...\n"); 455 G.removeDefinedSymbol(*Sym); 456 } 457 } 458 459 // Delete any unused blocks. 460 { 461 LLVM_DEBUG(dbgs() << "Dead-stripping blocks:\n"); 462 std::vector<Block *> BlocksToRemove; 463 for (auto *B : G.blocks()) 464 if (!VisitedBlocks.count(B)) 465 BlocksToRemove.push_back(B); 466 for (auto *B : BlocksToRemove) { 467 LLVM_DEBUG(dbgs() << " " << *B << "...\n"); 468 G.removeBlock(*B); 469 } 470 } 471 472 // Collect all external symbols to remove, then remove them. 473 { 474 LLVM_DEBUG(dbgs() << "Removing unused external symbols:\n"); 475 std::vector<Symbol *> SymbolsToRemove; 476 for (auto *Sym : G.external_symbols()) 477 if (!Sym->isLive()) 478 SymbolsToRemove.push_back(Sym); 479 for (auto *Sym : SymbolsToRemove) { 480 LLVM_DEBUG(dbgs() << " " << *Sym << "...\n"); 481 G.removeExternalSymbol(*Sym); 482 } 483 } 484 } 485 486 } // end namespace jitlink 487 } // end namespace llvm 488