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