1 //===-------- JITLink_EHFrameSupport.cpp - JITLink eh-frame utils ---------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "EHFrameSupportImpl.h" 10 11 #include "llvm/BinaryFormat/Dwarf.h" 12 #include "llvm/Config/config.h" 13 #include "llvm/ExecutionEngine/Orc/TargetProcess/RegisterEHFrames.h" 14 #include "llvm/Support/DynamicLibrary.h" 15 16 #define DEBUG_TYPE "jitlink" 17 18 namespace llvm { 19 namespace jitlink { 20 21 EHFrameEdgeFixer::EHFrameEdgeFixer(StringRef EHFrameSectionName, 22 unsigned PointerSize, Edge::Kind Pointer32, 23 Edge::Kind Pointer64, Edge::Kind Delta32, 24 Edge::Kind Delta64, Edge::Kind NegDelta32) 25 : EHFrameSectionName(EHFrameSectionName), PointerSize(PointerSize), 26 Pointer32(Pointer32), Pointer64(Pointer64), Delta32(Delta32), 27 Delta64(Delta64), NegDelta32(NegDelta32) {} 28 29 Error EHFrameEdgeFixer::operator()(LinkGraph &G) { 30 auto *EHFrame = G.findSectionByName(EHFrameSectionName); 31 32 if (!EHFrame) { 33 LLVM_DEBUG({ 34 dbgs() << "EHFrameEdgeFixer: No " << EHFrameSectionName 35 << " section in \"" << G.getName() << "\". Nothing to do.\n"; 36 }); 37 return Error::success(); 38 } 39 40 // Check that we support the graph's pointer size. 41 if (G.getPointerSize() != 4 && G.getPointerSize() != 8) 42 return make_error<JITLinkError>( 43 "EHFrameEdgeFixer only supports 32 and 64 bit targets"); 44 45 LLVM_DEBUG({ 46 dbgs() << "EHFrameEdgeFixer: Processing " << EHFrameSectionName << " in \"" 47 << G.getName() << "\"...\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 llvm::append_range(EHFrameBlocks, EHFrame->blocks()); 74 llvm::sort(EHFrameBlocks, [](const Block *LHS, const Block *RHS) { 75 return LHS->getAddress() < RHS->getAddress(); 76 }); 77 78 // Loop over the blocks in address order. 79 for (auto *B : EHFrameBlocks) 80 if (auto Err = processBlock(PC, *B)) 81 return Err; 82 83 return Error::success(); 84 } 85 86 static Expected<size_t> readCFIRecordLength(const Block &B, 87 BinaryStreamReader &R) { 88 uint32_t Length; 89 if (auto Err = R.readInteger(Length)) 90 return std::move(Err); 91 92 // If Length < 0xffffffff then use the regular length field, otherwise 93 // read the extended length field. 94 if (Length != 0xffffffff) 95 return Length; 96 97 uint64_t ExtendedLength; 98 if (auto Err = R.readInteger(ExtendedLength)) 99 return std::move(Err); 100 101 if (ExtendedLength > std::numeric_limits<size_t>::max()) 102 return make_error<JITLinkError>( 103 "In CFI record at " + 104 formatv("{0:x}", B.getAddress() + R.getOffset() - 12) + 105 ", extended length of " + formatv("{0:x}", ExtendedLength) + 106 " exceeds address-range max (" + 107 formatv("{0:x}", std::numeric_limits<size_t>::max())); 108 109 return ExtendedLength; 110 } 111 112 Error EHFrameEdgeFixer::processBlock(ParseContext &PC, Block &B) { 113 114 LLVM_DEBUG(dbgs() << " Processing block at " << B.getAddress() << "\n"); 115 116 // eh-frame should not contain zero-fill blocks. 117 if (B.isZeroFill()) 118 return make_error<JITLinkError>("Unexpected zero-fill block in " + 119 EHFrameSectionName + " section"); 120 121 if (B.getSize() == 0) { 122 LLVM_DEBUG(dbgs() << " Block is empty. Skipping.\n"); 123 return Error::success(); 124 } 125 126 // Find the offsets of any existing edges from this block. 127 BlockEdgesInfo BlockEdges; 128 for (auto &E : B.edges()) 129 if (E.isRelocation()) { 130 // Check if we already saw more than one relocation at this offset. 131 if (BlockEdges.Multiple.contains(E.getOffset())) 132 continue; 133 134 // Otherwise check if we previously had exactly one relocation at this 135 // offset. If so, we now have a second one and move it from the TargetMap 136 // into the Multiple set. 137 auto [It, Inserted] = BlockEdges.TargetMap.try_emplace(E.getOffset(), E); 138 if (!Inserted) { 139 BlockEdges.TargetMap.erase(It); 140 BlockEdges.Multiple.insert(E.getOffset()); 141 } 142 } 143 144 BinaryStreamReader BlockReader( 145 StringRef(B.getContent().data(), B.getContent().size()), 146 PC.G.getEndianness()); 147 148 // Get the record length. 149 Expected<size_t> RecordRemaining = readCFIRecordLength(B, BlockReader); 150 if (!RecordRemaining) 151 return RecordRemaining.takeError(); 152 153 // We expect DWARFRecordSectionSplitter to split each CFI record into its own 154 // block. 155 if (BlockReader.bytesRemaining() != *RecordRemaining) 156 return make_error<JITLinkError>("Incomplete CFI record at " + 157 formatv("{0:x16}", B.getAddress())); 158 159 // Read the CIE delta for this record. 160 uint64_t CIEDeltaFieldOffset = BlockReader.getOffset(); 161 uint32_t CIEDelta; 162 if (auto Err = BlockReader.readInteger(CIEDelta)) 163 return Err; 164 165 if (CIEDelta == 0) { 166 if (auto Err = processCIE(PC, B, CIEDeltaFieldOffset, BlockEdges)) 167 return Err; 168 } else { 169 if (auto Err = processFDE(PC, B, CIEDeltaFieldOffset, CIEDelta, BlockEdges)) 170 return Err; 171 } 172 173 return Error::success(); 174 } 175 176 Error EHFrameEdgeFixer::processCIE(ParseContext &PC, Block &B, 177 size_t CIEDeltaFieldOffset, 178 const BlockEdgesInfo &BlockEdges) { 179 180 LLVM_DEBUG(dbgs() << " Record is CIE\n"); 181 182 BinaryStreamReader RecordReader( 183 StringRef(B.getContent().data(), B.getContent().size()), 184 PC.G.getEndianness()); 185 186 // Skip past the CIE delta field: we've already processed this far. 187 RecordReader.setOffset(CIEDeltaFieldOffset + 4); 188 189 auto &CIESymbol = PC.G.addAnonymousSymbol(B, 0, B.getSize(), false, false); 190 CIEInformation CIEInfo(CIESymbol); 191 192 uint8_t Version = 0; 193 if (auto Err = RecordReader.readInteger(Version)) 194 return Err; 195 196 if (Version != 0x01) 197 return make_error<JITLinkError>("Bad CIE version " + Twine(Version) + 198 " (should be 0x01) in eh-frame"); 199 200 auto AugInfo = parseAugmentationString(RecordReader); 201 if (!AugInfo) 202 return AugInfo.takeError(); 203 204 // Skip the EH Data field if present. 205 if (AugInfo->EHDataFieldPresent) 206 if (auto Err = RecordReader.skip(PC.G.getPointerSize())) 207 return Err; 208 209 // Read and validate the code alignment factor. 210 { 211 uint64_t CodeAlignmentFactor = 0; 212 if (auto Err = RecordReader.readULEB128(CodeAlignmentFactor)) 213 return Err; 214 } 215 216 // Read and validate the data alignment factor. 217 { 218 int64_t DataAlignmentFactor = 0; 219 if (auto Err = RecordReader.readSLEB128(DataAlignmentFactor)) 220 return Err; 221 } 222 223 // Skip the return address register field. 224 if (auto Err = RecordReader.skip(1)) 225 return Err; 226 227 if (AugInfo->AugmentationDataPresent) { 228 229 CIEInfo.AugmentationDataPresent = true; 230 231 uint64_t AugmentationDataLength = 0; 232 if (auto Err = RecordReader.readULEB128(AugmentationDataLength)) 233 return Err; 234 235 uint32_t AugmentationDataStartOffset = RecordReader.getOffset(); 236 237 uint8_t *NextField = &AugInfo->Fields[0]; 238 while (uint8_t Field = *NextField++) { 239 switch (Field) { 240 case 'L': 241 CIEInfo.LSDAPresent = true; 242 if (auto PE = readPointerEncoding(RecordReader, B, "LSDA")) 243 CIEInfo.LSDAEncoding = *PE; 244 else 245 return PE.takeError(); 246 break; 247 case 'P': { 248 auto PersonalityPointerEncoding = 249 readPointerEncoding(RecordReader, B, "personality"); 250 if (!PersonalityPointerEncoding) 251 return PersonalityPointerEncoding.takeError(); 252 if (auto Err = 253 getOrCreateEncodedPointerEdge( 254 PC, BlockEdges, *PersonalityPointerEncoding, RecordReader, 255 B, RecordReader.getOffset(), "personality") 256 .takeError()) 257 return Err; 258 break; 259 } 260 case 'R': 261 if (auto PE = readPointerEncoding(RecordReader, B, "address")) { 262 CIEInfo.AddressEncoding = *PE; 263 if (CIEInfo.AddressEncoding == dwarf::DW_EH_PE_omit) 264 return make_error<JITLinkError>( 265 "Invalid address encoding DW_EH_PE_omit in CIE at " + 266 formatv("{0:x}", B.getAddress().getValue())); 267 } else 268 return PE.takeError(); 269 break; 270 default: 271 llvm_unreachable("Invalid augmentation string field"); 272 } 273 } 274 275 if (RecordReader.getOffset() - AugmentationDataStartOffset > 276 AugmentationDataLength) 277 return make_error<JITLinkError>("Read past the end of the augmentation " 278 "data while parsing fields"); 279 } 280 281 assert(!PC.CIEInfos.count(CIESymbol.getAddress()) && 282 "Multiple CIEs recorded at the same address?"); 283 PC.CIEInfos[CIESymbol.getAddress()] = std::move(CIEInfo); 284 285 return Error::success(); 286 } 287 288 Error EHFrameEdgeFixer::processFDE(ParseContext &PC, Block &B, 289 size_t CIEDeltaFieldOffset, 290 uint32_t CIEDelta, 291 const BlockEdgesInfo &BlockEdges) { 292 LLVM_DEBUG(dbgs() << " Record is FDE\n"); 293 294 orc::ExecutorAddr RecordAddress = B.getAddress(); 295 296 BinaryStreamReader RecordReader( 297 StringRef(B.getContent().data(), B.getContent().size()), 298 PC.G.getEndianness()); 299 300 // Skip past the CIE delta field: we've already read this far. 301 RecordReader.setOffset(CIEDeltaFieldOffset + 4); 302 303 auto &FDESymbol = PC.G.addAnonymousSymbol(B, 0, B.getSize(), false, false); 304 305 CIEInformation *CIEInfo = nullptr; 306 307 { 308 // Process the CIE pointer field. 309 if (BlockEdges.Multiple.contains(CIEDeltaFieldOffset)) 310 return make_error<JITLinkError>( 311 "CIE pointer field already has multiple edges at " + 312 formatv("{0:x16}", RecordAddress + CIEDeltaFieldOffset)); 313 314 auto CIEEdgeItr = BlockEdges.TargetMap.find(CIEDeltaFieldOffset); 315 316 orc::ExecutorAddr CIEAddress = 317 RecordAddress + orc::ExecutorAddrDiff(CIEDeltaFieldOffset) - 318 orc::ExecutorAddrDiff(CIEDelta); 319 if (CIEEdgeItr == BlockEdges.TargetMap.end()) { 320 LLVM_DEBUG({ 321 dbgs() << " Adding edge at " 322 << (RecordAddress + CIEDeltaFieldOffset) 323 << " to CIE at: " << CIEAddress << "\n"; 324 }); 325 if (auto CIEInfoOrErr = PC.findCIEInfo(CIEAddress)) 326 CIEInfo = *CIEInfoOrErr; 327 else 328 return CIEInfoOrErr.takeError(); 329 assert(CIEInfo->CIESymbol && "CIEInfo has no CIE symbol set"); 330 B.addEdge(NegDelta32, CIEDeltaFieldOffset, *CIEInfo->CIESymbol, 0); 331 } else { 332 LLVM_DEBUG({ 333 dbgs() << " Already has edge at " 334 << (RecordAddress + CIEDeltaFieldOffset) << " to CIE at " 335 << CIEAddress << "\n"; 336 }); 337 auto &EI = CIEEdgeItr->second; 338 if (EI.Addend) 339 return make_error<JITLinkError>( 340 "CIE edge at " + 341 formatv("{0:x16}", RecordAddress + CIEDeltaFieldOffset) + 342 " has non-zero addend"); 343 if (auto CIEInfoOrErr = PC.findCIEInfo(EI.Target->getAddress())) 344 CIEInfo = *CIEInfoOrErr; 345 else 346 return CIEInfoOrErr.takeError(); 347 } 348 } 349 350 // Process the PC-Begin field. 351 LLVM_DEBUG({ 352 dbgs() << " Processing PC-begin at " 353 << (RecordAddress + RecordReader.getOffset()) << "\n"; 354 }); 355 if (auto PCBegin = getOrCreateEncodedPointerEdge( 356 PC, BlockEdges, CIEInfo->AddressEncoding, RecordReader, B, 357 RecordReader.getOffset(), "PC begin")) { 358 assert(*PCBegin && "PC-begin symbol not set"); 359 if ((*PCBegin)->isDefined()) { 360 // Add a keep-alive edge from the FDE target to the FDE to ensure that the 361 // FDE is kept alive if its target is. 362 LLVM_DEBUG({ 363 dbgs() << " Adding keep-alive edge from target at " 364 << (*PCBegin)->getBlock().getAddress() << " to FDE at " 365 << RecordAddress << "\n"; 366 }); 367 (*PCBegin)->getBlock().addEdge(Edge::KeepAlive, 0, FDESymbol, 0); 368 } else { 369 LLVM_DEBUG({ 370 dbgs() << " WARNING: Not adding keep-alive edge to FDE at " 371 << RecordAddress << ", which points to " 372 << ((*PCBegin)->isExternal() ? "external" : "absolute") 373 << " symbol \"" << (*PCBegin)->getName() 374 << "\" -- FDE must be kept alive manually or it will be " 375 << "dead stripped.\n"; 376 }); 377 } 378 } else 379 return PCBegin.takeError(); 380 381 // Skip over the PC range size field. 382 if (auto Err = skipEncodedPointer(CIEInfo->AddressEncoding, RecordReader)) 383 return Err; 384 385 if (CIEInfo->AugmentationDataPresent) { 386 uint64_t AugmentationDataSize; 387 if (auto Err = RecordReader.readULEB128(AugmentationDataSize)) 388 return Err; 389 390 if (CIEInfo->LSDAPresent) 391 if (auto Err = getOrCreateEncodedPointerEdge( 392 PC, BlockEdges, CIEInfo->LSDAEncoding, RecordReader, B, 393 RecordReader.getOffset(), "LSDA") 394 .takeError()) 395 return Err; 396 } else { 397 LLVM_DEBUG(dbgs() << " Record does not have LSDA field.\n"); 398 } 399 400 return Error::success(); 401 } 402 403 Expected<EHFrameEdgeFixer::AugmentationInfo> 404 EHFrameEdgeFixer::parseAugmentationString(BinaryStreamReader &RecordReader) { 405 AugmentationInfo AugInfo; 406 uint8_t NextChar; 407 uint8_t *NextField = &AugInfo.Fields[0]; 408 409 if (auto Err = RecordReader.readInteger(NextChar)) 410 return std::move(Err); 411 412 while (NextChar != 0) { 413 switch (NextChar) { 414 case 'z': 415 AugInfo.AugmentationDataPresent = true; 416 break; 417 case 'e': 418 if (auto Err = RecordReader.readInteger(NextChar)) 419 return std::move(Err); 420 if (NextChar != 'h') 421 return make_error<JITLinkError>("Unrecognized substring e" + 422 Twine(NextChar) + 423 " in augmentation string"); 424 AugInfo.EHDataFieldPresent = true; 425 break; 426 case 'L': 427 case 'P': 428 case 'R': 429 *NextField++ = NextChar; 430 break; 431 default: 432 return make_error<JITLinkError>("Unrecognized character " + 433 Twine(NextChar) + 434 " in augmentation string"); 435 } 436 437 if (auto Err = RecordReader.readInteger(NextChar)) 438 return std::move(Err); 439 } 440 441 return std::move(AugInfo); 442 } 443 444 Expected<uint8_t> EHFrameEdgeFixer::readPointerEncoding(BinaryStreamReader &R, 445 Block &InBlock, 446 const char *FieldName) { 447 using namespace dwarf; 448 449 uint8_t PointerEncoding; 450 if (auto Err = R.readInteger(PointerEncoding)) 451 return std::move(Err); 452 453 bool Supported = true; 454 switch (PointerEncoding & 0xf) { 455 case DW_EH_PE_uleb128: 456 case DW_EH_PE_udata2: 457 case DW_EH_PE_sleb128: 458 case DW_EH_PE_sdata2: 459 Supported = false; 460 break; 461 } 462 if (Supported) { 463 switch (PointerEncoding & 0x70) { 464 case DW_EH_PE_textrel: 465 case DW_EH_PE_datarel: 466 case DW_EH_PE_funcrel: 467 case DW_EH_PE_aligned: 468 Supported = false; 469 break; 470 } 471 } 472 473 if (Supported) 474 return PointerEncoding; 475 476 return make_error<JITLinkError>("Unsupported pointer encoding " + 477 formatv("{0:x2}", PointerEncoding) + " for " + 478 FieldName + "in CFI record at " + 479 formatv("{0:x16}", InBlock.getAddress())); 480 } 481 482 Error EHFrameEdgeFixer::skipEncodedPointer(uint8_t PointerEncoding, 483 BinaryStreamReader &RecordReader) { 484 using namespace dwarf; 485 486 // Switch absptr to corresponding udata encoding. 487 if ((PointerEncoding & 0xf) == DW_EH_PE_absptr) 488 PointerEncoding |= (PointerSize == 8) ? DW_EH_PE_udata8 : DW_EH_PE_udata4; 489 490 switch (PointerEncoding & 0xf) { 491 case DW_EH_PE_udata4: 492 case DW_EH_PE_sdata4: 493 if (auto Err = RecordReader.skip(4)) 494 return Err; 495 break; 496 case DW_EH_PE_udata8: 497 case DW_EH_PE_sdata8: 498 if (auto Err = RecordReader.skip(8)) 499 return Err; 500 break; 501 default: 502 llvm_unreachable("Unrecognized encoding"); 503 } 504 return Error::success(); 505 } 506 507 Expected<Symbol *> EHFrameEdgeFixer::getOrCreateEncodedPointerEdge( 508 ParseContext &PC, const BlockEdgesInfo &BlockEdges, uint8_t PointerEncoding, 509 BinaryStreamReader &RecordReader, Block &BlockToFix, 510 size_t PointerFieldOffset, const char *FieldName) { 511 using namespace dwarf; 512 513 if (PointerEncoding == DW_EH_PE_omit) 514 return nullptr; 515 516 // If there's already an edge here then just skip the encoded pointer and 517 // return the edge's target. 518 { 519 auto EdgeI = BlockEdges.TargetMap.find(PointerFieldOffset); 520 if (EdgeI != BlockEdges.TargetMap.end()) { 521 LLVM_DEBUG({ 522 dbgs() << " Existing edge at " 523 << (BlockToFix.getAddress() + PointerFieldOffset) << " to " 524 << FieldName << " at " << EdgeI->second.Target->getAddress(); 525 if (EdgeI->second.Target->hasName()) 526 dbgs() << " (" << EdgeI->second.Target->getName() << ")"; 527 dbgs() << "\n"; 528 }); 529 if (auto Err = skipEncodedPointer(PointerEncoding, RecordReader)) 530 return std::move(Err); 531 return EdgeI->second.Target; 532 } 533 534 if (BlockEdges.Multiple.contains(PointerFieldOffset)) 535 return make_error<JITLinkError>("Multiple relocations at offset " + 536 formatv("{0:x16}", PointerFieldOffset)); 537 } 538 539 // Switch absptr to corresponding udata encoding. 540 if ((PointerEncoding & 0xf) == DW_EH_PE_absptr) 541 PointerEncoding |= (PointerSize == 8) ? DW_EH_PE_udata8 : DW_EH_PE_udata4; 542 543 // We need to create an edge. Start by reading the field value. 544 uint64_t FieldValue; 545 bool Is64Bit = false; 546 switch (PointerEncoding & 0xf) { 547 case DW_EH_PE_udata4: { 548 uint32_t Val; 549 if (auto Err = RecordReader.readInteger(Val)) 550 return std::move(Err); 551 FieldValue = Val; 552 break; 553 } 554 case DW_EH_PE_sdata4: { 555 uint32_t Val; 556 if (auto Err = RecordReader.readInteger(Val)) 557 return std::move(Err); 558 FieldValue = Val; 559 break; 560 } 561 case DW_EH_PE_udata8: 562 case DW_EH_PE_sdata8: 563 Is64Bit = true; 564 if (auto Err = RecordReader.readInteger(FieldValue)) 565 return std::move(Err); 566 break; 567 default: 568 llvm_unreachable("Unsupported encoding"); 569 } 570 571 // Find the edge target and edge kind to use. 572 orc::ExecutorAddr Target; 573 Edge::Kind PtrEdgeKind = Edge::Invalid; 574 if ((PointerEncoding & 0x70) == DW_EH_PE_pcrel) { 575 Target = BlockToFix.getAddress() + PointerFieldOffset; 576 PtrEdgeKind = Is64Bit ? Delta64 : Delta32; 577 } else 578 PtrEdgeKind = Is64Bit ? Pointer64 : Pointer32; 579 Target += FieldValue; 580 581 // Find or create a symbol to point the edge at. 582 auto TargetSym = getOrCreateSymbol(PC, Target); 583 if (!TargetSym) 584 return TargetSym.takeError(); 585 BlockToFix.addEdge(PtrEdgeKind, PointerFieldOffset, *TargetSym, 0); 586 587 LLVM_DEBUG({ 588 dbgs() << " Adding edge at " 589 << (BlockToFix.getAddress() + PointerFieldOffset) << " to " 590 << FieldName << " at " << TargetSym->getAddress(); 591 if (TargetSym->hasName()) 592 dbgs() << " (" << TargetSym->getName() << ")"; 593 dbgs() << "\n"; 594 }); 595 596 return &*TargetSym; 597 } 598 599 Expected<Symbol &> EHFrameEdgeFixer::getOrCreateSymbol(ParseContext &PC, 600 orc::ExecutorAddr Addr) { 601 // See whether we have a canonical symbol for the given address already. 602 auto CanonicalSymI = PC.AddrToSym.find(Addr); 603 if (CanonicalSymI != PC.AddrToSym.end()) 604 return *CanonicalSymI->second; 605 606 // Otherwise search for a block covering the address and create a new symbol. 607 auto *B = PC.AddrToBlock.getBlockCovering(Addr); 608 if (!B) 609 return make_error<JITLinkError>("No symbol or block covering address " + 610 formatv("{0:x16}", Addr)); 611 612 auto &S = 613 PC.G.addAnonymousSymbol(*B, Addr - B->getAddress(), 0, false, false); 614 PC.AddrToSym[S.getAddress()] = &S; 615 return S; 616 } 617 618 char EHFrameNullTerminator::NullTerminatorBlockContent[4] = {0, 0, 0, 0}; 619 620 EHFrameNullTerminator::EHFrameNullTerminator(StringRef EHFrameSectionName) 621 : EHFrameSectionName(EHFrameSectionName) {} 622 623 Error EHFrameNullTerminator::operator()(LinkGraph &G) { 624 auto *EHFrame = G.findSectionByName(EHFrameSectionName); 625 626 if (!EHFrame) 627 return Error::success(); 628 629 LLVM_DEBUG({ 630 dbgs() << "EHFrameNullTerminator adding null terminator to " 631 << EHFrameSectionName << "\n"; 632 }); 633 634 auto &NullTerminatorBlock = 635 G.createContentBlock(*EHFrame, NullTerminatorBlockContent, 636 orc::ExecutorAddr(~uint64_t(4)), 1, 0); 637 G.addAnonymousSymbol(NullTerminatorBlock, 0, 4, false, true); 638 return Error::success(); 639 } 640 641 EHFrameCFIBlockInspector EHFrameCFIBlockInspector::FromEdgeScan(Block &B) { 642 if (B.edges_empty()) 643 return EHFrameCFIBlockInspector(nullptr); 644 if (B.edges_size() == 1) 645 return EHFrameCFIBlockInspector(&*B.edges().begin()); 646 SmallVector<Edge *, 3> Es(llvm::make_pointer_range(B.edges())); 647 assert(Es.size() >= 2 && Es.size() <= 3 && "Unexpected number of edges"); 648 llvm::sort(Es, [](const Edge *LHS, const Edge *RHS) { 649 return LHS->getOffset() < RHS->getOffset(); 650 }); 651 return EHFrameCFIBlockInspector(*Es[0], *Es[1], 652 Es.size() == 3 ? Es[2] : nullptr); 653 return EHFrameCFIBlockInspector(nullptr); 654 } 655 656 EHFrameCFIBlockInspector::EHFrameCFIBlockInspector(Edge *PersonalityEdge) 657 : PersonalityEdge(PersonalityEdge) {} 658 659 EHFrameCFIBlockInspector::EHFrameCFIBlockInspector(Edge &CIEEdge, 660 Edge &PCBeginEdge, 661 Edge *LSDAEdge) 662 : CIEEdge(&CIEEdge), PCBeginEdge(&PCBeginEdge), LSDAEdge(LSDAEdge) {} 663 664 Section *getEHFrameSection(LinkGraph &G) { 665 const char *EHFrameSectionName = nullptr; 666 switch (G.getTargetTriple().getObjectFormat()) { 667 case Triple::MachO: 668 EHFrameSectionName = "__TEXT,__eh_frame"; 669 break; 670 case Triple::ELF: 671 EHFrameSectionName = ".eh_frame"; 672 break; 673 default: 674 return nullptr; 675 } 676 677 if (auto *S = G.findSectionByName(EHFrameSectionName)) 678 if (!S->empty()) 679 return S; 680 681 return nullptr; 682 } 683 684 } // end namespace jitlink 685 } // end namespace llvm 686