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