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