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