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