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