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