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