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