1 //===-------- JITLink_EHFrameSupport.cpp - JITLink eh-frame utils ---------===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 10 #include "EHFrameSupportImpl.h" 11 12 #include "llvm/BinaryFormat/Dwarf.h" 13 #include "llvm/Config/config.h" 14 #include "llvm/ExecutionEngine/Orc/TargetProcess/RegisterEHFrames.h" 15 #include "llvm/Support/DynamicLibrary.h" 16 17 #define DEBUG_TYPE "jitlink" 18 19 namespace llvm { 20 namespace jitlink { 21 22 EHFrameSplitter::EHFrameSplitter(StringRef EHFrameSectionName) 23 : EHFrameSectionName(EHFrameSectionName) {} 24 25 Error EHFrameSplitter::operator()(LinkGraph &G) { 26 auto *EHFrame = G.findSectionByName(EHFrameSectionName); 27 28 if (!EHFrame) { 29 LLVM_DEBUG({ 30 dbgs() << "EHFrameSplitter: No " << EHFrameSectionName 31 << " section. Nothing to do\n"; 32 }); 33 return Error::success(); 34 } 35 36 LLVM_DEBUG({ 37 dbgs() << "EHFrameSplitter: Processing " << EHFrameSectionName << "...\n"; 38 }); 39 40 DenseMap<Block *, LinkGraph::SplitBlockCache> Caches; 41 42 { 43 // Pre-build the split caches. 44 for (auto *B : EHFrame->blocks()) 45 Caches[B] = LinkGraph::SplitBlockCache::value_type(); 46 for (auto *Sym : EHFrame->symbols()) 47 Caches[&Sym->getBlock()]->push_back(Sym); 48 for (auto *B : EHFrame->blocks()) 49 llvm::sort(*Caches[B], [](const Symbol *LHS, const Symbol *RHS) { 50 return LHS->getOffset() > RHS->getOffset(); 51 }); 52 } 53 54 // Iterate over blocks (we do this by iterating over Caches entries rather 55 // than EHFrame->blocks() as we will be inserting new blocks along the way, 56 // which would invalidate iterators in the latter sequence. 57 for (auto &KV : Caches) { 58 auto &B = *KV.first; 59 auto &BCache = KV.second; 60 if (auto Err = processBlock(G, B, BCache)) 61 return Err; 62 } 63 64 return Error::success(); 65 } 66 67 Error EHFrameSplitter::processBlock(LinkGraph &G, Block &B, 68 LinkGraph::SplitBlockCache &Cache) { 69 LLVM_DEBUG({ 70 dbgs() << " Processing block at " << formatv("{0:x16}", B.getAddress()) 71 << "\n"; 72 }); 73 74 // eh-frame should not contain zero-fill blocks. 75 if (B.isZeroFill()) 76 return make_error<JITLinkError>("Unexpected zero-fill block in " + 77 EHFrameSectionName + " section"); 78 79 if (B.getSize() == 0) { 80 LLVM_DEBUG(dbgs() << " Block is empty. Skipping.\n"); 81 return Error::success(); 82 } 83 84 BinaryStreamReader BlockReader(B.getContent(), G.getEndianness()); 85 86 while (true) { 87 uint64_t RecordStartOffset = BlockReader.getOffset(); 88 89 LLVM_DEBUG({ 90 dbgs() << " Processing CFI record at " 91 << formatv("{0:x16}", B.getAddress()) << "\n"; 92 }); 93 94 uint32_t Length; 95 if (auto Err = BlockReader.readInteger(Length)) 96 return Err; 97 if (Length != 0xffffffff) { 98 if (auto Err = BlockReader.skip(Length)) 99 return Err; 100 } else { 101 uint64_t ExtendedLength; 102 if (auto Err = BlockReader.readInteger(ExtendedLength)) 103 return Err; 104 if (auto Err = BlockReader.skip(ExtendedLength)) 105 return Err; 106 } 107 108 // If this was the last block then there's nothing to split 109 if (BlockReader.empty()) { 110 LLVM_DEBUG(dbgs() << " Extracted " << B << "\n"); 111 return Error::success(); 112 } 113 114 uint64_t BlockSize = BlockReader.getOffset() - RecordStartOffset; 115 auto &NewBlock = G.splitBlock(B, BlockSize); 116 (void)NewBlock; 117 LLVM_DEBUG(dbgs() << " Extracted " << NewBlock << "\n"); 118 } 119 } 120 121 EHFrameEdgeFixer::EHFrameEdgeFixer(StringRef EHFrameSectionName, 122 Edge::Kind Delta64, Edge::Kind NegDelta32) 123 : EHFrameSectionName(EHFrameSectionName), Delta64(Delta64), 124 NegDelta32(NegDelta32) {} 125 126 Error EHFrameEdgeFixer::operator()(LinkGraph &G) { 127 auto *EHFrame = G.findSectionByName(EHFrameSectionName); 128 129 if (!EHFrame) { 130 LLVM_DEBUG({ 131 dbgs() << "EHFrameEdgeFixer: No " << EHFrameSectionName 132 << " section. Nothing to do\n"; 133 }); 134 return Error::success(); 135 } 136 137 LLVM_DEBUG({ 138 dbgs() << "EHFrameEdgeFixer: Processing " << EHFrameSectionName << "...\n"; 139 }); 140 141 ParseContext PC(G); 142 143 // Build a map of all blocks and symbols in the text sections. We will use 144 // these for finding / building edge targets when processing FDEs. 145 for (auto &Sec : G.sections()) { 146 PC.AddrToSyms.addSymbols(Sec.symbols()); 147 if (auto Err = PC.AddrToBlock.addBlocks(Sec.blocks(), 148 BlockAddressMap::includeNonNull)) 149 return Err; 150 } 151 152 // Sort eh-frame blocks into address order to ensure we visit CIEs before 153 // their child FDEs. 154 std::vector<Block *> EHFrameBlocks; 155 for (auto *B : EHFrame->blocks()) 156 EHFrameBlocks.push_back(B); 157 llvm::sort(EHFrameBlocks, [](const Block *LHS, const Block *RHS) { 158 return LHS->getAddress() < RHS->getAddress(); 159 }); 160 161 // Loop over the blocks in address order. 162 for (auto *B : EHFrameBlocks) 163 if (auto Err = processBlock(PC, *B)) 164 return Err; 165 166 return Error::success(); 167 } 168 169 Error EHFrameEdgeFixer::processBlock(ParseContext &PC, Block &B) { 170 171 LLVM_DEBUG({ 172 dbgs() << " Processing block at " << formatv("{0:x16}", B.getAddress()) 173 << "\n"; 174 }); 175 176 // eh-frame should not contain zero-fill blocks. 177 if (B.isZeroFill()) 178 return make_error<JITLinkError>("Unexpected zero-fill block in " + 179 EHFrameSectionName + " section"); 180 181 if (B.getSize() == 0) { 182 LLVM_DEBUG(dbgs() << " Block is empty. Skipping.\n"); 183 return Error::success(); 184 } 185 186 // Find the offsets of any existing edges from this block. 187 BlockEdgeMap BlockEdges; 188 for (auto &E : B.edges()) 189 if (E.isRelocation()) { 190 if (BlockEdges.count(E.getOffset())) 191 return make_error<JITLinkError>( 192 "Multiple relocations at offset " + 193 formatv("{0:x16}", E.getOffset()) + " in " + EHFrameSectionName + 194 " block at address " + formatv("{0:x16}", B.getAddress())); 195 196 BlockEdges[E.getOffset()] = EdgeTarget(E); 197 } 198 199 CIEInfosMap CIEInfos; 200 BinaryStreamReader BlockReader(B.getContent(), PC.G.getEndianness()); 201 while (!BlockReader.empty()) { 202 size_t RecordStartOffset = BlockReader.getOffset(); 203 204 LLVM_DEBUG({ 205 dbgs() << " Processing CFI record at " 206 << formatv("{0:x16}", B.getAddress() + RecordStartOffset) << "\n"; 207 }); 208 209 // Get the record length. 210 size_t RecordRemaining; 211 { 212 uint32_t Length; 213 if (auto Err = BlockReader.readInteger(Length)) 214 return Err; 215 // If Length < 0xffffffff then use the regular length field, otherwise 216 // read the extended length field. 217 if (Length != 0xffffffff) 218 RecordRemaining = Length; 219 else { 220 uint64_t ExtendedLength; 221 if (auto Err = BlockReader.readInteger(ExtendedLength)) 222 return Err; 223 RecordRemaining = ExtendedLength; 224 } 225 } 226 227 if (BlockReader.bytesRemaining() < RecordRemaining) 228 return make_error<JITLinkError>( 229 "Incomplete CFI record at " + 230 formatv("{0:x16}", B.getAddress() + RecordStartOffset)); 231 232 // Read the CIE delta for this record. 233 uint64_t CIEDeltaFieldOffset = BlockReader.getOffset() - RecordStartOffset; 234 uint32_t CIEDelta; 235 if (auto Err = BlockReader.readInteger(CIEDelta)) 236 return Err; 237 238 if (CIEDelta == 0) { 239 if (auto Err = processCIE(PC, B, RecordStartOffset, 240 CIEDeltaFieldOffset + RecordRemaining, 241 CIEDeltaFieldOffset)) 242 return Err; 243 } else { 244 if (auto Err = processFDE(PC, B, RecordStartOffset, 245 CIEDeltaFieldOffset + RecordRemaining, 246 CIEDeltaFieldOffset, CIEDelta, BlockEdges)) 247 return Err; 248 } 249 250 // Move to the next record. 251 BlockReader.setOffset(RecordStartOffset + CIEDeltaFieldOffset + 252 RecordRemaining); 253 } 254 255 return Error::success(); 256 } 257 258 Error EHFrameEdgeFixer::processCIE(ParseContext &PC, Block &B, 259 size_t RecordOffset, size_t RecordLength, 260 size_t CIEDeltaFieldOffset) { 261 using namespace dwarf; 262 263 LLVM_DEBUG(dbgs() << " Record is CIE\n"); 264 265 auto RecordContent = B.getContent().substr(RecordOffset, RecordLength); 266 BinaryStreamReader RecordReader(RecordContent, PC.G.getEndianness()); 267 268 // Skip past the CIE delta field: we've already processed this far. 269 RecordReader.setOffset(CIEDeltaFieldOffset + 4); 270 271 auto &CIESymbol = 272 PC.G.addAnonymousSymbol(B, RecordOffset, RecordLength, false, false); 273 CIEInformation CIEInfo(CIESymbol); 274 275 uint8_t Version = 0; 276 if (auto Err = RecordReader.readInteger(Version)) 277 return Err; 278 279 if (Version != 0x01) 280 return make_error<JITLinkError>("Bad CIE version " + Twine(Version) + 281 " (should be 0x01) in eh-frame"); 282 283 auto AugInfo = parseAugmentationString(RecordReader); 284 if (!AugInfo) 285 return AugInfo.takeError(); 286 287 // Skip the EH Data field if present. 288 if (AugInfo->EHDataFieldPresent) 289 if (auto Err = RecordReader.skip(PC.G.getPointerSize())) 290 return Err; 291 292 // Read and sanity check the code alignment factor. 293 { 294 uint64_t CodeAlignmentFactor = 0; 295 if (auto Err = RecordReader.readULEB128(CodeAlignmentFactor)) 296 return Err; 297 if (CodeAlignmentFactor != 1) 298 return make_error<JITLinkError>("Unsupported CIE code alignment factor " + 299 Twine(CodeAlignmentFactor) + 300 " (expected 1)"); 301 } 302 303 // Read and sanity check the data alignment factor. 304 { 305 int64_t DataAlignmentFactor = 0; 306 if (auto Err = RecordReader.readSLEB128(DataAlignmentFactor)) 307 return Err; 308 if (DataAlignmentFactor != -8) 309 return make_error<JITLinkError>("Unsupported CIE data alignment factor " + 310 Twine(DataAlignmentFactor) + 311 " (expected -8)"); 312 } 313 314 // Skip the return address register field. 315 if (auto Err = RecordReader.skip(1)) 316 return Err; 317 318 uint64_t AugmentationDataLength = 0; 319 if (auto Err = RecordReader.readULEB128(AugmentationDataLength)) 320 return Err; 321 322 uint32_t AugmentationDataStartOffset = RecordReader.getOffset(); 323 324 uint8_t *NextField = &AugInfo->Fields[0]; 325 while (uint8_t Field = *NextField++) { 326 switch (Field) { 327 case 'L': { 328 CIEInfo.FDEsHaveLSDAField = true; 329 uint8_t LSDAPointerEncoding; 330 if (auto Err = RecordReader.readInteger(LSDAPointerEncoding)) 331 return Err; 332 if (LSDAPointerEncoding != (DW_EH_PE_pcrel | DW_EH_PE_absptr)) 333 return make_error<JITLinkError>( 334 "Unsupported LSDA pointer encoding " + 335 formatv("{0:x2}", LSDAPointerEncoding) + " in CIE at " + 336 formatv("{0:x16}", CIESymbol.getAddress())); 337 break; 338 } 339 case 'P': { 340 uint8_t PersonalityPointerEncoding = 0; 341 if (auto Err = RecordReader.readInteger(PersonalityPointerEncoding)) 342 return Err; 343 if (PersonalityPointerEncoding != 344 (DW_EH_PE_indirect | DW_EH_PE_pcrel | DW_EH_PE_sdata4)) 345 return make_error<JITLinkError>( 346 "Unspported personality pointer " 347 "encoding " + 348 formatv("{0:x2}", PersonalityPointerEncoding) + " in CIE at " + 349 formatv("{0:x16}", CIESymbol.getAddress())); 350 uint32_t PersonalityPointerAddress; 351 if (auto Err = RecordReader.readInteger(PersonalityPointerAddress)) 352 return Err; 353 break; 354 } 355 case 'R': { 356 uint8_t FDEPointerEncoding; 357 if (auto Err = RecordReader.readInteger(FDEPointerEncoding)) 358 return Err; 359 if (FDEPointerEncoding != (DW_EH_PE_pcrel | DW_EH_PE_absptr)) 360 return make_error<JITLinkError>( 361 "Unsupported FDE address pointer " 362 "encoding " + 363 formatv("{0:x2}", FDEPointerEncoding) + " in CIE at " + 364 formatv("{0:x16}", CIESymbol.getAddress())); 365 break; 366 } 367 default: 368 llvm_unreachable("Invalid augmentation string field"); 369 } 370 } 371 372 if (RecordReader.getOffset() - AugmentationDataStartOffset > 373 AugmentationDataLength) 374 return make_error<JITLinkError>("Read past the end of the augmentation " 375 "data while parsing fields"); 376 377 assert(!PC.CIEInfos.count(CIESymbol.getAddress()) && 378 "Multiple CIEs recorded at the same address?"); 379 PC.CIEInfos[CIESymbol.getAddress()] = std::move(CIEInfo); 380 381 return Error::success(); 382 } 383 384 Error EHFrameEdgeFixer::processFDE(ParseContext &PC, Block &B, 385 size_t RecordOffset, size_t RecordLength, 386 size_t CIEDeltaFieldOffset, 387 uint32_t CIEDelta, 388 BlockEdgeMap &BlockEdges) { 389 LLVM_DEBUG(dbgs() << " Record is FDE\n"); 390 391 JITTargetAddress RecordAddress = B.getAddress() + RecordOffset; 392 393 auto RecordContent = B.getContent().substr(RecordOffset, RecordLength); 394 BinaryStreamReader RecordReader(RecordContent, PC.G.getEndianness()); 395 396 // Skip past the CIE delta field: we've already read this far. 397 RecordReader.setOffset(CIEDeltaFieldOffset + 4); 398 399 auto &FDESymbol = 400 PC.G.addAnonymousSymbol(B, RecordOffset, RecordLength, false, false); 401 402 CIEInformation *CIEInfo = nullptr; 403 404 { 405 // Process the CIE pointer field. 406 auto CIEEdgeItr = BlockEdges.find(RecordOffset + CIEDeltaFieldOffset); 407 JITTargetAddress CIEAddress = 408 RecordAddress + CIEDeltaFieldOffset - CIEDelta; 409 if (CIEEdgeItr == BlockEdges.end()) { 410 411 LLVM_DEBUG({ 412 dbgs() << " Adding edge at " 413 << formatv("{0:x16}", RecordAddress + CIEDeltaFieldOffset) 414 << " to CIE at: " << formatv("{0:x16}", CIEAddress) << "\n"; 415 }); 416 if (auto CIEInfoOrErr = PC.findCIEInfo(CIEAddress)) 417 CIEInfo = *CIEInfoOrErr; 418 else 419 return CIEInfoOrErr.takeError(); 420 assert(CIEInfo->CIESymbol && "CIEInfo has no CIE symbol set"); 421 B.addEdge(NegDelta32, RecordOffset + CIEDeltaFieldOffset, 422 *CIEInfo->CIESymbol, 0); 423 } else { 424 LLVM_DEBUG({ 425 dbgs() << " Already has edge at " 426 << formatv("{0:x16}", RecordAddress + CIEDeltaFieldOffset) 427 << " to CIE at " << formatv("{0:x16}", CIEAddress) << "\n"; 428 }); 429 auto &EI = CIEEdgeItr->second; 430 if (EI.Addend) 431 return make_error<JITLinkError>( 432 "CIE edge at " + 433 formatv("{0:x16}", RecordAddress + CIEDeltaFieldOffset) + 434 " has non-zero addend"); 435 if (auto CIEInfoOrErr = PC.findCIEInfo(EI.Target->getAddress())) 436 CIEInfo = *CIEInfoOrErr; 437 else 438 return CIEInfoOrErr.takeError(); 439 } 440 } 441 442 { 443 // Process the PC-Begin field. 444 Block *PCBeginBlock = nullptr; 445 JITTargetAddress PCBeginFieldOffset = RecordReader.getOffset(); 446 auto PCEdgeItr = BlockEdges.find(RecordOffset + PCBeginFieldOffset); 447 if (PCEdgeItr == BlockEdges.end()) { 448 auto PCBeginDelta = readAbsolutePointer(PC.G, RecordReader); 449 if (!PCBeginDelta) 450 return PCBeginDelta.takeError(); 451 JITTargetAddress PCBegin = 452 RecordAddress + PCBeginFieldOffset + *PCBeginDelta; 453 LLVM_DEBUG({ 454 dbgs() << " Adding edge at " 455 << formatv("{0:x16}", RecordAddress + PCBeginFieldOffset) 456 << " to PC at " << formatv("{0:x16}", PCBegin) << "\n"; 457 }); 458 auto PCBeginSym = getOrCreateSymbol(PC, PCBegin); 459 if (!PCBeginSym) 460 return PCBeginSym.takeError(); 461 B.addEdge(Delta64, RecordOffset + PCBeginFieldOffset, *PCBeginSym, 0); 462 PCBeginBlock = &PCBeginSym->getBlock(); 463 } else { 464 auto &EI = PCEdgeItr->second; 465 LLVM_DEBUG({ 466 dbgs() << " Already has edge at " 467 << formatv("{0:x16}", RecordAddress + PCBeginFieldOffset) 468 << " to PC at " << formatv("{0:x16}", EI.Target->getAddress()); 469 if (EI.Addend) 470 dbgs() << " + " << formatv("{0:x16}", EI.Addend); 471 dbgs() << "\n"; 472 }); 473 474 // Make sure the existing edge points at a defined block. 475 if (!EI.Target->isDefined()) { 476 auto EdgeAddr = RecordAddress + PCBeginFieldOffset; 477 return make_error<JITLinkError>("FDE edge at " + 478 formatv("{0:x16}", EdgeAddr) + 479 " points at external block"); 480 } 481 PCBeginBlock = &EI.Target->getBlock(); 482 if (auto Err = RecordReader.skip(PC.G.getPointerSize())) 483 return Err; 484 } 485 486 // Add a keep-alive edge from the FDE target to the FDE to ensure that the 487 // FDE is kept alive if its target is. 488 assert(PCBeginBlock && "PC-begin block not recorded"); 489 PCBeginBlock->addEdge(Edge::KeepAlive, 0, FDESymbol, 0); 490 } 491 492 // Skip over the PC range size field. 493 if (auto Err = RecordReader.skip(PC.G.getPointerSize())) 494 return Err; 495 496 if (CIEInfo->FDEsHaveLSDAField) { 497 uint64_t AugmentationDataSize; 498 if (auto Err = RecordReader.readULEB128(AugmentationDataSize)) 499 return Err; 500 if (AugmentationDataSize != PC.G.getPointerSize()) 501 return make_error<JITLinkError>( 502 "Unexpected FDE augmentation data size (expected " + 503 Twine(PC.G.getPointerSize()) + ", got " + 504 Twine(AugmentationDataSize) + ") for FDE at " + 505 formatv("{0:x16}", RecordAddress)); 506 507 JITTargetAddress LSDAFieldOffset = RecordReader.getOffset(); 508 auto LSDAEdgeItr = BlockEdges.find(RecordOffset + LSDAFieldOffset); 509 if (LSDAEdgeItr == BlockEdges.end()) { 510 auto LSDADelta = readAbsolutePointer(PC.G, RecordReader); 511 if (!LSDADelta) 512 return LSDADelta.takeError(); 513 JITTargetAddress LSDA = RecordAddress + LSDAFieldOffset + *LSDADelta; 514 auto LSDASym = getOrCreateSymbol(PC, LSDA); 515 if (!LSDASym) 516 return LSDASym.takeError(); 517 LLVM_DEBUG({ 518 dbgs() << " Adding edge at " 519 << formatv("{0:x16}", RecordAddress + LSDAFieldOffset) 520 << " to LSDA at " << formatv("{0:x16}", LSDA) << "\n"; 521 }); 522 B.addEdge(Delta64, RecordOffset + LSDAFieldOffset, *LSDASym, 0); 523 } else { 524 LLVM_DEBUG({ 525 auto &EI = LSDAEdgeItr->second; 526 dbgs() << " Already has edge at " 527 << formatv("{0:x16}", RecordAddress + LSDAFieldOffset) 528 << " to LSDA at " << formatv("{0:x16}", EI.Target->getAddress()); 529 if (EI.Addend) 530 dbgs() << " + " << formatv("{0:x16}", EI.Addend); 531 dbgs() << "\n"; 532 }); 533 if (auto Err = RecordReader.skip(PC.G.getPointerSize())) 534 return Err; 535 } 536 } else { 537 LLVM_DEBUG(dbgs() << " Record does not have LSDA field.\n"); 538 } 539 540 return Error::success(); 541 } 542 543 Expected<EHFrameEdgeFixer::AugmentationInfo> 544 EHFrameEdgeFixer::parseAugmentationString(BinaryStreamReader &RecordReader) { 545 AugmentationInfo AugInfo; 546 uint8_t NextChar; 547 uint8_t *NextField = &AugInfo.Fields[0]; 548 549 if (auto Err = RecordReader.readInteger(NextChar)) 550 return std::move(Err); 551 552 while (NextChar != 0) { 553 switch (NextChar) { 554 case 'z': 555 AugInfo.AugmentationDataPresent = true; 556 break; 557 case 'e': 558 if (auto Err = RecordReader.readInteger(NextChar)) 559 return std::move(Err); 560 if (NextChar != 'h') 561 return make_error<JITLinkError>("Unrecognized substring e" + 562 Twine(NextChar) + 563 " in augmentation string"); 564 AugInfo.EHDataFieldPresent = true; 565 break; 566 case 'L': 567 case 'P': 568 case 'R': 569 *NextField++ = NextChar; 570 break; 571 default: 572 return make_error<JITLinkError>("Unrecognized character " + 573 Twine(NextChar) + 574 " in augmentation string"); 575 } 576 577 if (auto Err = RecordReader.readInteger(NextChar)) 578 return std::move(Err); 579 } 580 581 return std::move(AugInfo); 582 } 583 584 Expected<JITTargetAddress> 585 EHFrameEdgeFixer::readAbsolutePointer(LinkGraph &G, 586 BinaryStreamReader &RecordReader) { 587 static_assert(sizeof(JITTargetAddress) == sizeof(uint64_t), 588 "Result must be able to hold a uint64_t"); 589 JITTargetAddress Addr; 590 if (G.getPointerSize() == 8) { 591 if (auto Err = RecordReader.readInteger(Addr)) 592 return std::move(Err); 593 } else if (G.getPointerSize() == 4) { 594 uint32_t Addr32; 595 if (auto Err = RecordReader.readInteger(Addr32)) 596 return std::move(Err); 597 Addr = Addr32; 598 } else 599 llvm_unreachable("Pointer size is not 32-bit or 64-bit"); 600 return Addr; 601 } 602 603 Expected<Symbol &> EHFrameEdgeFixer::getOrCreateSymbol(ParseContext &PC, 604 JITTargetAddress Addr) { 605 Symbol *CanonicalSym = nullptr; 606 607 auto UpdateCanonicalSym = [&](Symbol *Sym) { 608 if (!CanonicalSym || Sym->getLinkage() < CanonicalSym->getLinkage() || 609 Sym->getScope() < CanonicalSym->getScope() || 610 (Sym->hasName() && !CanonicalSym->hasName()) || 611 Sym->getName() < CanonicalSym->getName()) 612 CanonicalSym = Sym; 613 }; 614 615 if (auto *SymbolsAtAddr = PC.AddrToSyms.getSymbolsAt(Addr)) 616 for (auto *Sym : *SymbolsAtAddr) 617 UpdateCanonicalSym(Sym); 618 619 // If we found an existing symbol at the given address then use it. 620 if (CanonicalSym) 621 return *CanonicalSym; 622 623 // Otherwise search for a block covering the address and create a new symbol. 624 auto *B = PC.AddrToBlock.getBlockCovering(Addr); 625 if (!B) 626 return make_error<JITLinkError>("No symbol or block covering address " + 627 formatv("{0:x16}", Addr)); 628 629 return PC.G.addAnonymousSymbol(*B, Addr - B->getAddress(), 0, false, false); 630 } 631 632 EHFrameRegistrar::~EHFrameRegistrar() {} 633 634 Error InProcessEHFrameRegistrar::registerEHFrames( 635 JITTargetAddress EHFrameSectionAddr, size_t EHFrameSectionSize) { 636 return orc::registerEHFrameSection( 637 jitTargetAddressToPointer<void *>(EHFrameSectionAddr), 638 EHFrameSectionSize); 639 } 640 641 Error InProcessEHFrameRegistrar::deregisterEHFrames( 642 JITTargetAddress EHFrameSectionAddr, size_t EHFrameSectionSize) { 643 return orc::deregisterEHFrameSection( 644 jitTargetAddressToPointer<void *>(EHFrameSectionAddr), 645 EHFrameSectionSize); 646 } 647 648 LinkGraphPassFunction 649 createEHFrameRecorderPass(const Triple &TT, 650 StoreFrameRangeFunction StoreRangeAddress) { 651 const char *EHFrameSectionName = nullptr; 652 if (TT.getObjectFormat() == Triple::MachO) 653 EHFrameSectionName = "__eh_frame"; 654 else 655 EHFrameSectionName = ".eh_frame"; 656 657 auto RecordEHFrame = 658 [EHFrameSectionName, 659 StoreFrameRange = std::move(StoreRangeAddress)](LinkGraph &G) -> Error { 660 // Search for a non-empty eh-frame and record the address of the first 661 // symbol in it. 662 JITTargetAddress Addr = 0; 663 size_t Size = 0; 664 if (auto *S = G.findSectionByName(EHFrameSectionName)) { 665 auto R = SectionRange(*S); 666 Addr = R.getStart(); 667 Size = R.getSize(); 668 } 669 if (Addr == 0 && Size != 0) 670 return make_error<JITLinkError>("__eh_frame section can not have zero " 671 "address with non-zero size"); 672 StoreFrameRange(Addr, Size); 673 return Error::success(); 674 }; 675 676 return RecordEHFrame; 677 } 678 679 } // end namespace jitlink 680 } // end namespace llvm 681