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