1 //===-------- JITLink_EHFrameSupport.cpp - JITLink eh-frame utils ---------===// 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 "EHFrameSupportImpl.h" 10 11 #include "llvm/BinaryFormat/Dwarf.h" 12 #include "llvm/Config/config.h" 13 #include "llvm/ExecutionEngine/Orc/TargetProcess/RegisterEHFrames.h" 14 #include "llvm/Support/DynamicLibrary.h" 15 16 #define DEBUG_TYPE "jitlink" 17 18 namespace llvm { 19 namespace jitlink { 20 21 DWARFRecordSectionSplitter::DWARFRecordSectionSplitter(StringRef SectionName) 22 : SectionName(SectionName) {} 23 24 Error DWARFRecordSectionSplitter::operator()(LinkGraph &G) { 25 auto *Section = G.findSectionByName(SectionName); 26 27 if (!Section) { 28 LLVM_DEBUG({ 29 dbgs() << "DWARFRecordSectionSplitter: No " << SectionName 30 << " section. Nothing to do\n"; 31 }); 32 return Error::success(); 33 } 34 35 LLVM_DEBUG({ 36 dbgs() << "DWARFRecordSectionSplitter: Processing " << SectionName 37 << "...\n"; 38 }); 39 40 DenseMap<Block *, LinkGraph::SplitBlockCache> Caches; 41 42 { 43 // Pre-build the split caches. 44 for (auto *B : Section->blocks()) 45 Caches[B] = LinkGraph::SplitBlockCache::value_type(); 46 for (auto *Sym : Section->symbols()) 47 Caches[&Sym->getBlock()]->push_back(Sym); 48 for (auto *B : Section->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 Section->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 DWARFRecordSectionSplitter::processBlock( 68 LinkGraph &G, Block &B, LinkGraph::SplitBlockCache &Cache) { 69 LLVM_DEBUG(dbgs() << " Processing block at " << B.getAddress() << "\n"); 70 71 // Section should not contain zero-fill blocks. 72 if (B.isZeroFill()) 73 return make_error<JITLinkError>("Unexpected zero-fill block in " + 74 SectionName + " section"); 75 76 if (B.getSize() == 0) { 77 LLVM_DEBUG(dbgs() << " Block is empty. Skipping.\n"); 78 return Error::success(); 79 } 80 81 BinaryStreamReader BlockReader( 82 StringRef(B.getContent().data(), B.getContent().size()), 83 G.getEndianness()); 84 85 while (true) { 86 uint64_t RecordStartOffset = BlockReader.getOffset(); 87 88 LLVM_DEBUG({ 89 dbgs() << " Processing CFI record at " 90 << formatv("{0:x16}", B.getAddress()) << "\n"; 91 }); 92 93 uint32_t Length; 94 if (auto Err = BlockReader.readInteger(Length)) 95 return Err; 96 if (Length != 0xffffffff) { 97 if (auto Err = BlockReader.skip(Length)) 98 return Err; 99 } else { 100 uint64_t ExtendedLength; 101 if (auto Err = BlockReader.readInteger(ExtendedLength)) 102 return Err; 103 if (auto Err = BlockReader.skip(ExtendedLength)) 104 return Err; 105 } 106 107 // If this was the last block then there's nothing to split 108 if (BlockReader.empty()) { 109 LLVM_DEBUG(dbgs() << " Extracted " << B << "\n"); 110 return Error::success(); 111 } 112 113 uint64_t BlockSize = BlockReader.getOffset() - RecordStartOffset; 114 auto &NewBlock = G.splitBlock(B, BlockSize); 115 (void)NewBlock; 116 LLVM_DEBUG(dbgs() << " Extracted " << NewBlock << "\n"); 117 } 118 } 119 120 EHFrameEdgeFixer::EHFrameEdgeFixer(StringRef EHFrameSectionName, 121 unsigned PointerSize, Edge::Kind Delta64, 122 Edge::Kind Delta32, Edge::Kind NegDelta32) 123 : EHFrameSectionName(EHFrameSectionName), PointerSize(PointerSize), 124 Delta64(Delta64), Delta32(Delta32), 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 // Check that we support the graph's pointer size. 138 if (G.getPointerSize() != 4 && G.getPointerSize() != 8) 139 return make_error<JITLinkError>( 140 "EHFrameEdgeFixer only supports 32 and 64 bit targets"); 141 142 LLVM_DEBUG({ 143 dbgs() << "EHFrameEdgeFixer: Processing " << EHFrameSectionName << "...\n"; 144 }); 145 146 ParseContext PC(G); 147 148 // Build a map of all blocks and symbols in the text sections. We will use 149 // these for finding / building edge targets when processing FDEs. 150 for (auto &Sec : G.sections()) { 151 PC.AddrToSyms.addSymbols(Sec.symbols()); 152 if (auto Err = PC.AddrToBlock.addBlocks(Sec.blocks(), 153 BlockAddressMap::includeNonNull)) 154 return Err; 155 } 156 157 // Sort eh-frame blocks into address order to ensure we visit CIEs before 158 // their child FDEs. 159 std::vector<Block *> EHFrameBlocks; 160 for (auto *B : EHFrame->blocks()) 161 EHFrameBlocks.push_back(B); 162 llvm::sort(EHFrameBlocks, [](const Block *LHS, const Block *RHS) { 163 return LHS->getAddress() < RHS->getAddress(); 164 }); 165 166 // Loop over the blocks in address order. 167 for (auto *B : EHFrameBlocks) 168 if (auto Err = processBlock(PC, *B)) 169 return Err; 170 171 return Error::success(); 172 } 173 174 Error EHFrameEdgeFixer::processBlock(ParseContext &PC, Block &B) { 175 176 LLVM_DEBUG({ 177 dbgs() << " Processing block at " << formatv("{0:x16}", B.getAddress()) 178 << "\n"; 179 }); 180 181 // eh-frame should not contain zero-fill blocks. 182 if (B.isZeroFill()) 183 return make_error<JITLinkError>("Unexpected zero-fill block in " + 184 EHFrameSectionName + " section"); 185 186 if (B.getSize() == 0) { 187 LLVM_DEBUG(dbgs() << " Block is empty. Skipping.\n"); 188 return Error::success(); 189 } 190 191 // Find the offsets of any existing edges from this block. 192 BlockEdgeMap BlockEdges; 193 for (auto &E : B.edges()) 194 if (E.isRelocation()) { 195 if (BlockEdges.count(E.getOffset())) 196 return make_error<JITLinkError>( 197 "Multiple relocations at offset " + 198 formatv("{0:x16}", E.getOffset()) + " in " + EHFrameSectionName + 199 " block at address " + formatv("{0:x16}", B.getAddress())); 200 201 BlockEdges[E.getOffset()] = EdgeTarget(E); 202 } 203 204 CIEInfosMap CIEInfos; 205 BinaryStreamReader BlockReader( 206 StringRef(B.getContent().data(), B.getContent().size()), 207 PC.G.getEndianness()); 208 while (!BlockReader.empty()) { 209 size_t RecordStartOffset = BlockReader.getOffset(); 210 211 LLVM_DEBUG({ 212 dbgs() << " Processing CFI record at " 213 << formatv("{0:x16}", B.getAddress() + RecordStartOffset) << "\n"; 214 }); 215 216 // Get the record length. 217 size_t RecordRemaining; 218 { 219 uint32_t Length; 220 if (auto Err = BlockReader.readInteger(Length)) 221 return Err; 222 // If Length < 0xffffffff then use the regular length field, otherwise 223 // read the extended length field. 224 if (Length != 0xffffffff) 225 RecordRemaining = Length; 226 else { 227 uint64_t ExtendedLength; 228 if (auto Err = BlockReader.readInteger(ExtendedLength)) 229 return Err; 230 RecordRemaining = ExtendedLength; 231 } 232 } 233 234 if (BlockReader.bytesRemaining() < RecordRemaining) 235 return make_error<JITLinkError>( 236 "Incomplete CFI record at " + 237 formatv("{0:x16}", B.getAddress() + RecordStartOffset)); 238 239 // Read the CIE delta for this record. 240 uint64_t CIEDeltaFieldOffset = BlockReader.getOffset() - RecordStartOffset; 241 uint32_t CIEDelta; 242 if (auto Err = BlockReader.readInteger(CIEDelta)) 243 return Err; 244 245 if (CIEDelta == 0) { 246 if (auto Err = processCIE(PC, B, RecordStartOffset, 247 CIEDeltaFieldOffset + RecordRemaining, 248 CIEDeltaFieldOffset)) 249 return Err; 250 } else { 251 if (auto Err = processFDE(PC, B, RecordStartOffset, 252 CIEDeltaFieldOffset + RecordRemaining, 253 CIEDeltaFieldOffset, CIEDelta, BlockEdges)) 254 return Err; 255 } 256 257 // Move to the next record. 258 BlockReader.setOffset(RecordStartOffset + CIEDeltaFieldOffset + 259 RecordRemaining); 260 } 261 262 return Error::success(); 263 } 264 265 Error EHFrameEdgeFixer::processCIE(ParseContext &PC, Block &B, 266 size_t RecordOffset, size_t RecordLength, 267 size_t CIEDeltaFieldOffset) { 268 269 LLVM_DEBUG(dbgs() << " Record is CIE\n"); 270 271 auto RecordContent = B.getContent().slice(RecordOffset, RecordLength); 272 BinaryStreamReader RecordReader( 273 StringRef(RecordContent.data(), RecordContent.size()), 274 PC.G.getEndianness()); 275 276 // Skip past the CIE delta field: we've already processed this far. 277 RecordReader.setOffset(CIEDeltaFieldOffset + 4); 278 279 auto &CIESymbol = 280 PC.G.addAnonymousSymbol(B, RecordOffset, RecordLength, false, false); 281 CIEInformation CIEInfo(CIESymbol); 282 283 uint8_t Version = 0; 284 if (auto Err = RecordReader.readInteger(Version)) 285 return Err; 286 287 if (Version != 0x01) 288 return make_error<JITLinkError>("Bad CIE version " + Twine(Version) + 289 " (should be 0x01) in eh-frame"); 290 291 auto AugInfo = parseAugmentationString(RecordReader); 292 if (!AugInfo) 293 return AugInfo.takeError(); 294 295 // Skip the EH Data field if present. 296 if (AugInfo->EHDataFieldPresent) 297 if (auto Err = RecordReader.skip(PC.G.getPointerSize())) 298 return Err; 299 300 // Read and validate the code alignment factor. 301 { 302 uint64_t CodeAlignmentFactor = 0; 303 if (auto Err = RecordReader.readULEB128(CodeAlignmentFactor)) 304 return Err; 305 if (CodeAlignmentFactor != 1) 306 return make_error<JITLinkError>("Unsupported CIE code alignment factor " + 307 Twine(CodeAlignmentFactor) + 308 " (expected 1)"); 309 } 310 311 // Read and validate the data alignment factor. 312 { 313 int64_t DataAlignmentFactor = 0; 314 if (auto Err = RecordReader.readSLEB128(DataAlignmentFactor)) 315 return Err; 316 if (DataAlignmentFactor != -8) 317 return make_error<JITLinkError>("Unsupported CIE data alignment factor " + 318 Twine(DataAlignmentFactor) + 319 " (expected -8)"); 320 } 321 322 // Skip the return address register field. 323 if (auto Err = RecordReader.skip(1)) 324 return Err; 325 326 uint64_t AugmentationDataLength = 0; 327 if (auto Err = RecordReader.readULEB128(AugmentationDataLength)) 328 return Err; 329 330 uint32_t AugmentationDataStartOffset = RecordReader.getOffset(); 331 332 uint8_t *NextField = &AugInfo->Fields[0]; 333 while (uint8_t Field = *NextField++) { 334 switch (Field) { 335 case 'L': { 336 CIEInfo.FDEsHaveLSDAField = true; 337 uint8_t LSDAPointerEncoding; 338 if (auto Err = RecordReader.readInteger(LSDAPointerEncoding)) 339 return Err; 340 if (!isSupportedPointerEncoding(LSDAPointerEncoding)) 341 return make_error<JITLinkError>( 342 "Unsupported LSDA pointer encoding " + 343 formatv("{0:x2}", LSDAPointerEncoding) + " in CIE at " + 344 formatv("{0:x16}", CIESymbol.getAddress())); 345 CIEInfo.LSDAPointerEncoding = LSDAPointerEncoding; 346 break; 347 } 348 case 'P': { 349 uint8_t PersonalityPointerEncoding = 0; 350 if (auto Err = RecordReader.readInteger(PersonalityPointerEncoding)) 351 return Err; 352 if (PersonalityPointerEncoding != 353 (dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel | 354 dwarf::DW_EH_PE_sdata4)) 355 return make_error<JITLinkError>( 356 "Unspported personality pointer " 357 "encoding " + 358 formatv("{0:x2}", PersonalityPointerEncoding) + " in CIE at " + 359 formatv("{0:x16}", CIESymbol.getAddress())); 360 uint32_t PersonalityPointerAddress; 361 if (auto Err = RecordReader.readInteger(PersonalityPointerAddress)) 362 return Err; 363 break; 364 } 365 case 'R': { 366 uint8_t FDEPointerEncoding; 367 if (auto Err = RecordReader.readInteger(FDEPointerEncoding)) 368 return Err; 369 if (!isSupportedPointerEncoding(FDEPointerEncoding)) 370 return make_error<JITLinkError>( 371 "Unsupported FDE pointer encoding " + 372 formatv("{0:x2}", FDEPointerEncoding) + " in CIE at " + 373 formatv("{0:x16}", CIESymbol.getAddress())); 374 CIEInfo.FDEPointerEncoding = FDEPointerEncoding; 375 break; 376 } 377 default: 378 llvm_unreachable("Invalid augmentation string field"); 379 } 380 } 381 382 if (RecordReader.getOffset() - AugmentationDataStartOffset > 383 AugmentationDataLength) 384 return make_error<JITLinkError>("Read past the end of the augmentation " 385 "data while parsing fields"); 386 387 assert(!PC.CIEInfos.count(CIESymbol.getAddress()) && 388 "Multiple CIEs recorded at the same address?"); 389 PC.CIEInfos[CIESymbol.getAddress()] = std::move(CIEInfo); 390 391 return Error::success(); 392 } 393 394 Error EHFrameEdgeFixer::processFDE(ParseContext &PC, Block &B, 395 size_t RecordOffset, size_t RecordLength, 396 size_t CIEDeltaFieldOffset, 397 uint32_t CIEDelta, 398 BlockEdgeMap &BlockEdges) { 399 LLVM_DEBUG(dbgs() << " Record is FDE\n"); 400 401 orc::ExecutorAddr RecordAddress = B.getAddress() + RecordOffset; 402 403 auto RecordContent = B.getContent().slice(RecordOffset, RecordLength); 404 BinaryStreamReader RecordReader( 405 StringRef(RecordContent.data(), RecordContent.size()), 406 PC.G.getEndianness()); 407 408 // Skip past the CIE delta field: we've already read this far. 409 RecordReader.setOffset(CIEDeltaFieldOffset + 4); 410 411 auto &FDESymbol = 412 PC.G.addAnonymousSymbol(B, RecordOffset, RecordLength, false, false); 413 414 CIEInformation *CIEInfo = nullptr; 415 416 { 417 // Process the CIE pointer field. 418 auto CIEEdgeItr = BlockEdges.find(RecordOffset + CIEDeltaFieldOffset); 419 orc::ExecutorAddr CIEAddress = 420 RecordAddress + orc::ExecutorAddrDiff(CIEDeltaFieldOffset) - 421 orc::ExecutorAddrDiff(CIEDelta); 422 if (CIEEdgeItr == BlockEdges.end()) { 423 424 LLVM_DEBUG({ 425 dbgs() << " Adding edge at " 426 << formatv("{0:x16}", RecordAddress + CIEDeltaFieldOffset) 427 << " to CIE at: " << formatv("{0:x16}", CIEAddress) << "\n"; 428 }); 429 if (auto CIEInfoOrErr = PC.findCIEInfo(CIEAddress)) 430 CIEInfo = *CIEInfoOrErr; 431 else 432 return CIEInfoOrErr.takeError(); 433 assert(CIEInfo->CIESymbol && "CIEInfo has no CIE symbol set"); 434 B.addEdge(NegDelta32, RecordOffset + CIEDeltaFieldOffset, 435 *CIEInfo->CIESymbol, 0); 436 } else { 437 LLVM_DEBUG({ 438 dbgs() << " Already has edge at " 439 << formatv("{0:x16}", RecordAddress + CIEDeltaFieldOffset) 440 << " to CIE at " << formatv("{0:x16}", CIEAddress) << "\n"; 441 }); 442 auto &EI = CIEEdgeItr->second; 443 if (EI.Addend) 444 return make_error<JITLinkError>( 445 "CIE edge at " + 446 formatv("{0:x16}", RecordAddress + CIEDeltaFieldOffset) + 447 " has non-zero addend"); 448 if (auto CIEInfoOrErr = PC.findCIEInfo(EI.Target->getAddress())) 449 CIEInfo = *CIEInfoOrErr; 450 else 451 return CIEInfoOrErr.takeError(); 452 } 453 } 454 455 { 456 // Process the PC-Begin field. 457 Block *PCBeginBlock = nullptr; 458 orc::ExecutorAddrDiff PCBeginFieldOffset = RecordReader.getOffset(); 459 auto PCEdgeItr = BlockEdges.find(RecordOffset + PCBeginFieldOffset); 460 if (PCEdgeItr == BlockEdges.end()) { 461 auto PCBeginPtrInfo = 462 readEncodedPointer(CIEInfo->FDEPointerEncoding, 463 RecordAddress + PCBeginFieldOffset, RecordReader); 464 if (!PCBeginPtrInfo) 465 return PCBeginPtrInfo.takeError(); 466 orc::ExecutorAddr PCBegin = PCBeginPtrInfo->first; 467 Edge::Kind PCBeginEdgeKind = PCBeginPtrInfo->second; 468 LLVM_DEBUG({ 469 dbgs() << " Adding edge at " 470 << (RecordAddress + PCBeginFieldOffset) << " to PC at " 471 << formatv("{0:x16}", PCBegin) << "\n"; 472 }); 473 auto PCBeginSym = getOrCreateSymbol(PC, PCBegin); 474 if (!PCBeginSym) 475 return PCBeginSym.takeError(); 476 B.addEdge(PCBeginEdgeKind, RecordOffset + PCBeginFieldOffset, *PCBeginSym, 477 0); 478 PCBeginBlock = &PCBeginSym->getBlock(); 479 } else { 480 auto &EI = PCEdgeItr->second; 481 LLVM_DEBUG({ 482 dbgs() << " Already has edge at " 483 << formatv("{0:x16}", RecordAddress + PCBeginFieldOffset) 484 << " to PC at " << formatv("{0:x16}", EI.Target->getAddress()); 485 if (EI.Addend) 486 dbgs() << " + " << formatv("{0:x16}", EI.Addend); 487 dbgs() << "\n"; 488 }); 489 490 // Make sure the existing edge points at a defined block. 491 if (!EI.Target->isDefined()) { 492 auto EdgeAddr = RecordAddress + PCBeginFieldOffset; 493 return make_error<JITLinkError>("FDE edge at " + 494 formatv("{0:x16}", EdgeAddr) + 495 " points at external block"); 496 } 497 PCBeginBlock = &EI.Target->getBlock(); 498 if (auto Err = RecordReader.skip( 499 getPointerEncodingDataSize(CIEInfo->FDEPointerEncoding))) 500 return Err; 501 } 502 503 // Add a keep-alive edge from the FDE target to the FDE to ensure that the 504 // FDE is kept alive if its target is. 505 assert(PCBeginBlock && "PC-begin block not recorded"); 506 LLVM_DEBUG({ 507 dbgs() << " Adding keep-alive edge from target at " 508 << formatv("{0:x16}", PCBeginBlock->getAddress()) << " to FDE at " 509 << formatv("{0:x16}", RecordAddress) << "\n"; 510 }); 511 PCBeginBlock->addEdge(Edge::KeepAlive, 0, FDESymbol, 0); 512 } 513 514 // Skip over the PC range size field. 515 if (auto Err = RecordReader.skip( 516 getPointerEncodingDataSize(CIEInfo->FDEPointerEncoding))) 517 return Err; 518 519 if (CIEInfo->FDEsHaveLSDAField) { 520 uint64_t AugmentationDataSize; 521 if (auto Err = RecordReader.readULEB128(AugmentationDataSize)) 522 return Err; 523 524 orc::ExecutorAddrDiff LSDAFieldOffset = RecordReader.getOffset(); 525 auto LSDAEdgeItr = BlockEdges.find(RecordOffset + LSDAFieldOffset); 526 if (LSDAEdgeItr == BlockEdges.end()) { 527 auto LSDAPointerInfo = 528 readEncodedPointer(CIEInfo->LSDAPointerEncoding, 529 RecordAddress + LSDAFieldOffset, RecordReader); 530 if (!LSDAPointerInfo) 531 return LSDAPointerInfo.takeError(); 532 orc::ExecutorAddr LSDA = LSDAPointerInfo->first; 533 Edge::Kind LSDAEdgeKind = LSDAPointerInfo->second; 534 auto LSDASym = getOrCreateSymbol(PC, LSDA); 535 if (!LSDASym) 536 return LSDASym.takeError(); 537 LLVM_DEBUG({ 538 dbgs() << " Adding edge at " 539 << formatv("{0:x16}", RecordAddress + LSDAFieldOffset) 540 << " to LSDA at " << formatv("{0:x16}", LSDA) << "\n"; 541 }); 542 B.addEdge(LSDAEdgeKind, RecordOffset + LSDAFieldOffset, *LSDASym, 0); 543 } else { 544 LLVM_DEBUG({ 545 auto &EI = LSDAEdgeItr->second; 546 dbgs() << " Already has edge at " 547 << formatv("{0:x16}", RecordAddress + LSDAFieldOffset) 548 << " to LSDA at " << formatv("{0:x16}", EI.Target->getAddress()); 549 if (EI.Addend) 550 dbgs() << " + " << formatv("{0:x16}", EI.Addend); 551 dbgs() << "\n"; 552 }); 553 if (auto Err = RecordReader.skip(AugmentationDataSize)) 554 return Err; 555 } 556 } else { 557 LLVM_DEBUG(dbgs() << " Record does not have LSDA field.\n"); 558 } 559 560 return Error::success(); 561 } 562 563 Expected<EHFrameEdgeFixer::AugmentationInfo> 564 EHFrameEdgeFixer::parseAugmentationString(BinaryStreamReader &RecordReader) { 565 AugmentationInfo AugInfo; 566 uint8_t NextChar; 567 uint8_t *NextField = &AugInfo.Fields[0]; 568 569 if (auto Err = RecordReader.readInteger(NextChar)) 570 return std::move(Err); 571 572 while (NextChar != 0) { 573 switch (NextChar) { 574 case 'z': 575 AugInfo.AugmentationDataPresent = true; 576 break; 577 case 'e': 578 if (auto Err = RecordReader.readInteger(NextChar)) 579 return std::move(Err); 580 if (NextChar != 'h') 581 return make_error<JITLinkError>("Unrecognized substring e" + 582 Twine(NextChar) + 583 " in augmentation string"); 584 AugInfo.EHDataFieldPresent = true; 585 break; 586 case 'L': 587 case 'P': 588 case 'R': 589 *NextField++ = NextChar; 590 break; 591 default: 592 return make_error<JITLinkError>("Unrecognized character " + 593 Twine(NextChar) + 594 " in augmentation string"); 595 } 596 597 if (auto Err = RecordReader.readInteger(NextChar)) 598 return std::move(Err); 599 } 600 601 return std::move(AugInfo); 602 } 603 604 bool EHFrameEdgeFixer::isSupportedPointerEncoding(uint8_t PointerEncoding) { 605 using namespace dwarf; 606 607 // We only support PC-rel for now. 608 if ((PointerEncoding & 0x70) != DW_EH_PE_pcrel) 609 return false; 610 611 // readEncodedPointer does not handle indirect. 612 if (PointerEncoding & DW_EH_PE_indirect) 613 return false; 614 615 // Supported datatypes. 616 switch (PointerEncoding & 0xf) { 617 case DW_EH_PE_absptr: 618 case DW_EH_PE_udata4: 619 case DW_EH_PE_udata8: 620 case DW_EH_PE_sdata4: 621 case DW_EH_PE_sdata8: 622 return true; 623 } 624 625 return false; 626 } 627 628 unsigned EHFrameEdgeFixer::getPointerEncodingDataSize(uint8_t PointerEncoding) { 629 using namespace dwarf; 630 631 assert(isSupportedPointerEncoding(PointerEncoding) && 632 "Unsupported pointer encoding"); 633 switch (PointerEncoding & 0xf) { 634 case DW_EH_PE_absptr: 635 return PointerSize; 636 case DW_EH_PE_udata4: 637 case DW_EH_PE_sdata4: 638 return 4; 639 case DW_EH_PE_udata8: 640 case DW_EH_PE_sdata8: 641 return 8; 642 default: 643 llvm_unreachable("Unsupported encoding"); 644 } 645 } 646 647 Expected<std::pair<orc::ExecutorAddr, Edge::Kind>> 648 EHFrameEdgeFixer::readEncodedPointer(uint8_t PointerEncoding, 649 orc::ExecutorAddr PointerFieldAddress, 650 BinaryStreamReader &RecordReader) { 651 assert(isSupportedPointerEncoding(PointerEncoding) && 652 "Unsupported pointer encoding"); 653 654 using namespace dwarf; 655 656 // Isolate data type, remap absptr to udata4 or udata8. This relies on us 657 // having verified that the graph uses 32-bit or 64-bit pointers only at the 658 // start of this pass. 659 uint8_t EffectiveType = PointerEncoding & 0xf; 660 if (EffectiveType == DW_EH_PE_absptr) 661 EffectiveType = (PointerSize == 8) ? DW_EH_PE_udata8 : DW_EH_PE_udata4; 662 663 orc::ExecutorAddr Addr; 664 Edge::Kind PointerEdgeKind = Edge::Invalid; 665 switch (EffectiveType) { 666 case DW_EH_PE_udata4: { 667 uint32_t Val; 668 if (auto Err = RecordReader.readInteger(Val)) 669 return std::move(Err); 670 Addr = PointerFieldAddress + Val; 671 PointerEdgeKind = Delta32; 672 break; 673 } 674 case DW_EH_PE_udata8: { 675 uint64_t Val; 676 if (auto Err = RecordReader.readInteger(Val)) 677 return std::move(Err); 678 Addr = PointerFieldAddress + Val; 679 PointerEdgeKind = Delta64; 680 break; 681 } 682 case DW_EH_PE_sdata4: { 683 int32_t Val; 684 if (auto Err = RecordReader.readInteger(Val)) 685 return std::move(Err); 686 Addr = PointerFieldAddress + Val; 687 PointerEdgeKind = Delta32; 688 break; 689 } 690 case DW_EH_PE_sdata8: { 691 int64_t Val; 692 if (auto Err = RecordReader.readInteger(Val)) 693 return std::move(Err); 694 Addr = PointerFieldAddress + Val; 695 PointerEdgeKind = Delta64; 696 break; 697 } 698 } 699 700 if (PointerEdgeKind == Edge::Invalid) 701 return make_error<JITLinkError>( 702 "Unspported edge kind for encoded pointer at " + 703 formatv("{0:x}", PointerFieldAddress)); 704 705 return std::make_pair(Addr, Delta64); 706 } 707 708 Expected<Symbol &> EHFrameEdgeFixer::getOrCreateSymbol(ParseContext &PC, 709 orc::ExecutorAddr Addr) { 710 Symbol *CanonicalSym = nullptr; 711 712 auto UpdateCanonicalSym = [&](Symbol *Sym) { 713 if (!CanonicalSym || Sym->getLinkage() < CanonicalSym->getLinkage() || 714 Sym->getScope() < CanonicalSym->getScope() || 715 (Sym->hasName() && !CanonicalSym->hasName()) || 716 Sym->getName() < CanonicalSym->getName()) 717 CanonicalSym = Sym; 718 }; 719 720 if (auto *SymbolsAtAddr = PC.AddrToSyms.getSymbolsAt(Addr)) 721 for (auto *Sym : *SymbolsAtAddr) 722 UpdateCanonicalSym(Sym); 723 724 // If we found an existing symbol at the given address then use it. 725 if (CanonicalSym) 726 return *CanonicalSym; 727 728 // Otherwise search for a block covering the address and create a new symbol. 729 auto *B = PC.AddrToBlock.getBlockCovering(Addr); 730 if (!B) 731 return make_error<JITLinkError>("No symbol or block covering address " + 732 formatv("{0:x16}", Addr)); 733 734 return PC.G.addAnonymousSymbol(*B, Addr - B->getAddress(), 0, false, false); 735 } 736 737 char EHFrameNullTerminator::NullTerminatorBlockContent[4] = {0, 0, 0, 0}; 738 739 EHFrameNullTerminator::EHFrameNullTerminator(StringRef EHFrameSectionName) 740 : EHFrameSectionName(EHFrameSectionName) {} 741 742 Error EHFrameNullTerminator::operator()(LinkGraph &G) { 743 auto *EHFrame = G.findSectionByName(EHFrameSectionName); 744 745 if (!EHFrame) 746 return Error::success(); 747 748 LLVM_DEBUG({ 749 dbgs() << "EHFrameNullTerminator adding null terminator to " 750 << EHFrameSectionName << "\n"; 751 }); 752 753 auto &NullTerminatorBlock = 754 G.createContentBlock(*EHFrame, NullTerminatorBlockContent, 755 orc::ExecutorAddr(~uint64_t(4)), 1, 0); 756 G.addAnonymousSymbol(NullTerminatorBlock, 0, 4, false, true); 757 return Error::success(); 758 } 759 760 EHFrameRegistrar::~EHFrameRegistrar() = default; 761 762 Error InProcessEHFrameRegistrar::registerEHFrames( 763 orc::ExecutorAddrRange EHFrameSection) { 764 return orc::registerEHFrameSection(EHFrameSection.Start.toPtr<void *>(), 765 EHFrameSection.size()); 766 } 767 768 Error InProcessEHFrameRegistrar::deregisterEHFrames( 769 orc::ExecutorAddrRange EHFrameSection) { 770 return orc::deregisterEHFrameSection(EHFrameSection.Start.toPtr<void *>(), 771 EHFrameSection.size()); 772 } 773 774 LinkGraphPassFunction 775 createEHFrameRecorderPass(const Triple &TT, 776 StoreFrameRangeFunction StoreRangeAddress) { 777 const char *EHFrameSectionName = nullptr; 778 if (TT.getObjectFormat() == Triple::MachO) 779 EHFrameSectionName = "__TEXT,__eh_frame"; 780 else 781 EHFrameSectionName = ".eh_frame"; 782 783 auto RecordEHFrame = 784 [EHFrameSectionName, 785 StoreFrameRange = std::move(StoreRangeAddress)](LinkGraph &G) -> Error { 786 // Search for a non-empty eh-frame and record the address of the first 787 // symbol in it. 788 orc::ExecutorAddr Addr; 789 size_t Size = 0; 790 if (auto *S = G.findSectionByName(EHFrameSectionName)) { 791 auto R = SectionRange(*S); 792 Addr = R.getStart(); 793 Size = R.getSize(); 794 } 795 if (!Addr && Size != 0) 796 return make_error<JITLinkError>( 797 StringRef(EHFrameSectionName) + 798 " section can not have zero address with non-zero size"); 799 StoreFrameRange(Addr, Size); 800 return Error::success(); 801 }; 802 803 return RecordEHFrame; 804 } 805 806 } // end namespace jitlink 807 } // end namespace llvm 808