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