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/Support/DynamicLibrary.h" 14 15 #define DEBUG_TYPE "jitlink" 16 17 namespace llvm { 18 namespace jitlink { 19 20 EHFrameBinaryParser::EHFrameBinaryParser(JITTargetAddress EHFrameAddress, 21 StringRef EHFrameContent, 22 unsigned PointerSize, 23 support::endianness Endianness) 24 : EHFrameAddress(EHFrameAddress), EHFrameContent(EHFrameContent), 25 PointerSize(PointerSize), EHFrameReader(EHFrameContent, Endianness) {} 26 27 Error EHFrameBinaryParser::addToGraph() { 28 while (!EHFrameReader.empty()) { 29 size_t RecordOffset = EHFrameReader.getOffset(); 30 31 LLVM_DEBUG({ 32 dbgs() << "Processing eh-frame record at " 33 << format("0x%016" PRIx64, EHFrameAddress + RecordOffset) 34 << " (offset " << RecordOffset << ")\n"; 35 }); 36 37 size_t RecordLength = 0; 38 uint32_t RecordLengthField; 39 if (auto Err = EHFrameReader.readInteger(RecordLengthField)) 40 return Err; 41 42 // Process CIE/FDE length/extended-length fields to build the blocks. 43 // 44 // The value of these fields describe the length of the *rest* of the CIE 45 // (not including data up to the end of the field itself) so we have to 46 // bump RecordLength to include the data up to the end of the field: 4 bytes 47 // for Length, or 12 bytes (4 bytes + 8 bytes) for ExtendedLength. 48 if (RecordLengthField == 0) // Length 0 means end of __eh_frame section. 49 break; 50 51 // If the regular length field's value is 0xffffffff, use extended length. 52 if (RecordLengthField == 0xffffffff) { 53 uint64_t ExtendedLengthField; 54 if (auto Err = EHFrameReader.readInteger(ExtendedLengthField)) 55 return Err; 56 if (ExtendedLengthField > EHFrameReader.bytesRemaining()) 57 return make_error<JITLinkError>("CIE record extends past the end of " 58 "the __eh_frame section"); 59 if (ExtendedLengthField + 12 > std::numeric_limits<size_t>::max()) 60 return make_error<JITLinkError>("CIE record too large to process"); 61 RecordLength = ExtendedLengthField + 12; 62 } else { 63 if (RecordLengthField > EHFrameReader.bytesRemaining()) 64 return make_error<JITLinkError>("CIE record extends past the end of " 65 "the __eh_frame section"); 66 RecordLength = RecordLengthField + 4; 67 } 68 69 LLVM_DEBUG(dbgs() << " length: " << RecordLength << "\n"); 70 71 // Read the CIE Pointer. 72 size_t CIEPointerAddress = EHFrameAddress + EHFrameReader.getOffset(); 73 uint32_t CIEPointer; 74 if (auto Err = EHFrameReader.readInteger(CIEPointer)) 75 return Err; 76 77 // Based on the CIE pointer value, parse this as a CIE or FDE record. 78 if (CIEPointer == 0) { 79 if (auto Err = processCIE(RecordOffset, RecordLength)) 80 return Err; 81 } else { 82 if (auto Err = processFDE(RecordOffset, RecordLength, CIEPointerAddress, 83 CIEPointer)) 84 return Err; 85 } 86 87 EHFrameReader.setOffset(RecordOffset + RecordLength); 88 } 89 90 return Error::success(); 91 } 92 93 void EHFrameBinaryParser::anchor() {} 94 95 Expected<EHFrameBinaryParser::AugmentationInfo> 96 EHFrameBinaryParser::parseAugmentationString() { 97 AugmentationInfo AugInfo; 98 uint8_t NextChar; 99 uint8_t *NextField = &AugInfo.Fields[0]; 100 101 if (auto Err = EHFrameReader.readInteger(NextChar)) 102 return std::move(Err); 103 104 while (NextChar != 0) { 105 switch (NextChar) { 106 case 'z': 107 AugInfo.AugmentationDataPresent = true; 108 break; 109 case 'e': 110 if (auto Err = EHFrameReader.readInteger(NextChar)) 111 return std::move(Err); 112 if (NextChar != 'h') 113 return make_error<JITLinkError>("Unrecognized substring e" + 114 Twine(NextChar) + 115 " in augmentation string"); 116 AugInfo.EHDataFieldPresent = true; 117 break; 118 case 'L': 119 case 'P': 120 case 'R': 121 *NextField++ = NextChar; 122 break; 123 default: 124 return make_error<JITLinkError>("Unrecognized character " + 125 Twine(NextChar) + 126 " in augmentation string"); 127 } 128 129 if (auto Err = EHFrameReader.readInteger(NextChar)) 130 return std::move(Err); 131 } 132 133 return std::move(AugInfo); 134 } 135 136 Expected<JITTargetAddress> EHFrameBinaryParser::readAbsolutePointer() { 137 static_assert(sizeof(JITTargetAddress) == sizeof(uint64_t), 138 "Result must be able to hold a uint64_t"); 139 JITTargetAddress Addr; 140 if (PointerSize == 8) { 141 if (auto Err = EHFrameReader.readInteger(Addr)) 142 return std::move(Err); 143 } else if (PointerSize == 4) { 144 uint32_t Addr32; 145 if (auto Err = EHFrameReader.readInteger(Addr32)) 146 return std::move(Err); 147 Addr = Addr32; 148 } else 149 llvm_unreachable("Pointer size is not 32-bit or 64-bit"); 150 return Addr; 151 } 152 153 Error EHFrameBinaryParser::processCIE(size_t RecordOffset, 154 size_t RecordLength) { 155 // Use the dwarf namespace for convenient access to pointer encoding 156 // constants. 157 using namespace dwarf; 158 159 LLVM_DEBUG(dbgs() << " Record is CIE\n"); 160 161 auto &CIESymbol = 162 createCIERecord(EHFrameAddress + RecordOffset, 163 EHFrameContent.substr(RecordOffset, RecordLength)); 164 165 CIEInformation CIEInfo(CIESymbol); 166 167 uint8_t Version = 0; 168 if (auto Err = EHFrameReader.readInteger(Version)) 169 return Err; 170 171 if (Version != 0x01) 172 return make_error<JITLinkError>("Bad CIE version " + Twine(Version) + 173 " (should be 0x01) in eh-frame"); 174 175 auto AugInfo = parseAugmentationString(); 176 if (!AugInfo) 177 return AugInfo.takeError(); 178 179 // Skip the EH Data field if present. 180 if (AugInfo->EHDataFieldPresent) 181 if (auto Err = EHFrameReader.skip(PointerSize)) 182 return Err; 183 184 // Read and sanity check the code alignment factor. 185 { 186 uint64_t CodeAlignmentFactor = 0; 187 if (auto Err = EHFrameReader.readULEB128(CodeAlignmentFactor)) 188 return Err; 189 if (CodeAlignmentFactor != 1) 190 return make_error<JITLinkError>("Unsupported CIE code alignment factor " + 191 Twine(CodeAlignmentFactor) + 192 " (expected 1)"); 193 } 194 195 // Read and sanity check the data alignment factor. 196 { 197 int64_t DataAlignmentFactor = 0; 198 if (auto Err = EHFrameReader.readSLEB128(DataAlignmentFactor)) 199 return Err; 200 if (DataAlignmentFactor != -8) 201 return make_error<JITLinkError>("Unsupported CIE data alignment factor " + 202 Twine(DataAlignmentFactor) + 203 " (expected -8)"); 204 } 205 206 // Skip the return address register field. 207 if (auto Err = EHFrameReader.skip(1)) 208 return Err; 209 210 uint64_t AugmentationDataLength = 0; 211 if (auto Err = EHFrameReader.readULEB128(AugmentationDataLength)) 212 return Err; 213 214 uint32_t AugmentationDataStartOffset = EHFrameReader.getOffset(); 215 216 uint8_t *NextField = &AugInfo->Fields[0]; 217 while (uint8_t Field = *NextField++) { 218 switch (Field) { 219 case 'L': { 220 CIEInfo.FDEsHaveLSDAField = true; 221 uint8_t LSDAPointerEncoding; 222 if (auto Err = EHFrameReader.readInteger(LSDAPointerEncoding)) 223 return Err; 224 if (LSDAPointerEncoding != (DW_EH_PE_pcrel | DW_EH_PE_absptr)) 225 return make_error<JITLinkError>( 226 "Unsupported LSDA pointer encoding " + 227 formatv("{0:x2}", LSDAPointerEncoding) + " in CIE at " + 228 formatv("{0:x16}", CIESymbol.getAddress())); 229 break; 230 } 231 case 'P': { 232 uint8_t PersonalityPointerEncoding = 0; 233 if (auto Err = EHFrameReader.readInteger(PersonalityPointerEncoding)) 234 return Err; 235 if (PersonalityPointerEncoding != 236 (DW_EH_PE_indirect | DW_EH_PE_pcrel | DW_EH_PE_sdata4)) 237 return make_error<JITLinkError>( 238 "Unspported personality pointer " 239 "encoding " + 240 formatv("{0:x2}", PersonalityPointerEncoding) + " in CIE at " + 241 formatv("{0:x16}", CIESymbol.getAddress())); 242 uint32_t PersonalityPointerAddress; 243 if (auto Err = EHFrameReader.readInteger(PersonalityPointerAddress)) 244 return Err; 245 break; 246 } 247 case 'R': { 248 uint8_t FDEPointerEncoding; 249 if (auto Err = EHFrameReader.readInteger(FDEPointerEncoding)) 250 return Err; 251 if (FDEPointerEncoding != (DW_EH_PE_pcrel | DW_EH_PE_absptr)) 252 return make_error<JITLinkError>( 253 "Unsupported FDE address pointer " 254 "encoding " + 255 formatv("{0:x2}", FDEPointerEncoding) + " in CIE at " + 256 formatv("{0:x16}", CIESymbol.getAddress())); 257 break; 258 } 259 default: 260 llvm_unreachable("Invalid augmentation string field"); 261 } 262 } 263 264 if (EHFrameReader.getOffset() - AugmentationDataStartOffset > 265 AugmentationDataLength) 266 return make_error<JITLinkError>("Read past the end of the augmentation " 267 "data while parsing fields"); 268 269 assert(!CIEInfos.count(CIESymbol.getAddress()) && 270 "Multiple CIEs recorded at the same address?"); 271 CIEInfos[CIESymbol.getAddress()] = std::move(CIEInfo); 272 273 return Error::success(); 274 } 275 276 Error EHFrameBinaryParser::processFDE(size_t RecordOffset, size_t RecordLength, 277 JITTargetAddress CIEPointerAddress, 278 uint32_t CIEPointer) { 279 LLVM_DEBUG(dbgs() << " Record is FDE\n"); 280 281 LLVM_DEBUG({ 282 dbgs() << " CIE pointer: " 283 << format("0x%016" PRIx64, CIEPointerAddress - CIEPointer) << "\n"; 284 }); 285 286 auto CIEInfoItr = CIEInfos.find(CIEPointerAddress - CIEPointer); 287 if (CIEInfoItr == CIEInfos.end()) 288 return make_error<JITLinkError>( 289 "FDE at " + formatv("{0:x16}", EHFrameAddress + RecordOffset) + 290 " points to non-existant CIE at " + 291 formatv("{0:x16}", CIEPointerAddress - CIEPointer)); 292 auto &CIEInfo = CIEInfoItr->second; 293 294 // Read and sanity check the PC-start pointer and size. 295 JITTargetAddress PCBeginAddress = EHFrameAddress + EHFrameReader.getOffset(); 296 297 auto PCBeginDelta = readAbsolutePointer(); 298 if (!PCBeginDelta) 299 return PCBeginDelta.takeError(); 300 301 JITTargetAddress PCBegin = PCBeginAddress + *PCBeginDelta; 302 LLVM_DEBUG({ 303 dbgs() << " PC begin: " << format("0x%016" PRIx64, PCBegin) << "\n"; 304 }); 305 306 auto *TargetSymbol = getSymbolAtAddress(PCBegin); 307 308 if (!TargetSymbol) 309 return make_error<JITLinkError>("FDE PC-begin " + 310 formatv("{0:x16}", PCBegin) + 311 " does not point at symbol"); 312 313 if (TargetSymbol->getAddress() != PCBegin) 314 return make_error<JITLinkError>( 315 "FDE PC-begin " + formatv("{0:x16}", PCBegin) + 316 " does not point to start of symbol at " + 317 formatv("{0:x16}", TargetSymbol->getAddress())); 318 319 LLVM_DEBUG(dbgs() << " FDE target: " << *TargetSymbol << "\n"); 320 321 // Skip over the PC range size field. 322 if (auto Err = EHFrameReader.skip(PointerSize)) 323 return Err; 324 325 Symbol *LSDASymbol = nullptr; 326 JITTargetAddress LSDAAddress = 0; 327 if (CIEInfo.FDEsHaveLSDAField) { 328 uint64_t AugmentationDataSize; 329 if (auto Err = EHFrameReader.readULEB128(AugmentationDataSize)) 330 return Err; 331 if (AugmentationDataSize != PointerSize) 332 return make_error<JITLinkError>( 333 "Unexpected FDE augmentation data size (expected " + 334 Twine(PointerSize) + ", got " + Twine(AugmentationDataSize) + 335 ") for FDE at " + formatv("{0:x16}", EHFrameAddress + RecordOffset)); 336 LSDAAddress = EHFrameAddress + EHFrameReader.getOffset(); 337 auto LSDADelta = readAbsolutePointer(); 338 if (!LSDADelta) 339 return LSDADelta.takeError(); 340 341 JITTargetAddress LSDA = LSDAAddress + *LSDADelta; 342 343 LSDASymbol = getSymbolAtAddress(LSDA); 344 345 if (!LSDASymbol) 346 return make_error<JITLinkError>("FDE LSDA " + formatv("{0:x16}", LSDA) + 347 " does not point at symbol"); 348 349 if (LSDASymbol->getAddress() != LSDA) 350 return make_error<JITLinkError>( 351 "FDE LSDA " + formatv("{0:x16}", LSDA) + 352 " does not point to start of symbol at " + 353 formatv("{0:x16}", LSDASymbol->getAddress())); 354 355 LLVM_DEBUG(dbgs() << " FDE LSDA: " << *LSDASymbol << "\n"); 356 } 357 358 JITTargetAddress RecordAddress = EHFrameAddress + RecordOffset; 359 auto FDESymbol = createFDERecord( 360 RecordAddress, EHFrameContent.substr(RecordOffset, RecordLength), 361 *CIEInfo.CIESymbol, CIEPointerAddress - RecordAddress, *TargetSymbol, 362 PCBeginAddress - RecordAddress, LSDASymbol, LSDAAddress - RecordAddress); 363 364 return FDESymbol.takeError(); 365 } 366 367 // Determine whether we can register EH tables. 368 #if (defined(__GNUC__) && !defined(__ARM_EABI__) && !defined(__ia64__) && \ 369 !(defined(_AIX) && defined(__ibmxl__)) && !defined(__SEH__) && \ 370 !defined(__USING_SJLJ_EXCEPTIONS__)) 371 #define HAVE_EHTABLE_SUPPORT 1 372 #else 373 #define HAVE_EHTABLE_SUPPORT 0 374 #endif 375 376 #if HAVE_EHTABLE_SUPPORT 377 extern "C" void __register_frame(const void *); 378 extern "C" void __deregister_frame(const void *); 379 380 Error registerFrameWrapper(const void *P) { 381 __register_frame(P); 382 return Error::success(); 383 } 384 385 Error deregisterFrameWrapper(const void *P) { 386 __deregister_frame(P); 387 return Error::success(); 388 } 389 390 #else 391 392 // The building compiler does not have __(de)register_frame but 393 // it may be found at runtime in a dynamically-loaded library. 394 // For example, this happens when building LLVM with Visual C++ 395 // but using the MingW runtime. 396 static Error registerFrameWrapper(const void *P) { 397 static void((*RegisterFrame)(const void *)) = 0; 398 399 if (!RegisterFrame) 400 *(void **)&RegisterFrame = 401 llvm::sys::DynamicLibrary::SearchForAddressOfSymbol("__register_frame"); 402 403 if (RegisterFrame) { 404 RegisterFrame(P); 405 return Error::success(); 406 } 407 408 return make_error<JITLinkError>("could not register eh-frame: " 409 "__register_frame function not found"); 410 } 411 412 static Error deregisterFrameWrapper(const void *P) { 413 static void((*DeregisterFrame)(const void *)) = 0; 414 415 if (!DeregisterFrame) 416 *(void **)&DeregisterFrame = 417 llvm::sys::DynamicLibrary::SearchForAddressOfSymbol( 418 "__deregister_frame"); 419 420 if (DeregisterFrame) { 421 DeregisterFrame(P); 422 return Error::success(); 423 } 424 425 return make_error<JITLinkError>("could not deregister eh-frame: " 426 "__deregister_frame function not found"); 427 } 428 #endif 429 430 #ifdef __APPLE__ 431 432 template <typename HandleFDEFn> 433 Error walkAppleEHFrameSection(const char *const SectionStart, 434 size_t SectionSize, 435 HandleFDEFn HandleFDE) { 436 const char *CurCFIRecord = SectionStart; 437 const char *End = SectionStart + SectionSize; 438 uint64_t Size = *reinterpret_cast<const uint32_t *>(CurCFIRecord); 439 440 while (CurCFIRecord != End && Size != 0) { 441 const char *OffsetField = CurCFIRecord + (Size == 0xffffffff ? 12 : 4); 442 if (Size == 0xffffffff) 443 Size = *reinterpret_cast<const uint64_t *>(CurCFIRecord + 4) + 12; 444 else 445 Size += 4; 446 uint32_t Offset = *reinterpret_cast<const uint32_t *>(OffsetField); 447 if (Offset != 0) 448 if (auto Err = HandleFDE(CurCFIRecord)) 449 return Err; 450 451 LLVM_DEBUG({ 452 dbgs() << "Registering eh-frame section:\n"; 453 dbgs() << "Processing " << (Offset ? "FDE" : "CIE") << " @" 454 << (void *)CurCFIRecord << ": ["; 455 for (unsigned I = 0; I < Size; ++I) 456 dbgs() << format(" 0x%02" PRIx8, *(CurCFIRecord + I)); 457 dbgs() << " ]\n"; 458 }); 459 CurCFIRecord += Size; 460 461 Size = *reinterpret_cast<const uint32_t *>(CurCFIRecord); 462 } 463 464 return Error::success(); 465 } 466 467 #endif // __APPLE__ 468 469 Error registerEHFrameSection(const void *EHFrameSectionAddr, 470 size_t EHFrameSectionSize) { 471 #ifdef __APPLE__ 472 // On Darwin __register_frame has to be called for each FDE entry. 473 return walkAppleEHFrameSection(static_cast<const char *>(EHFrameSectionAddr), 474 EHFrameSectionSize, 475 registerFrameWrapper); 476 #else 477 // On Linux __register_frame takes a single argument: 478 // a pointer to the start of the .eh_frame section. 479 480 // How can it find the end? Because crtendS.o is linked 481 // in and it has an .eh_frame section with four zero chars. 482 return registerFrameWrapper(EHFrameSectionAddr); 483 #endif 484 } 485 486 Error deregisterEHFrameSection(const void *EHFrameSectionAddr, 487 size_t EHFrameSectionSize) { 488 #ifdef __APPLE__ 489 return walkAppleEHFrameSection(static_cast<const char *>(EHFrameSectionAddr), 490 EHFrameSectionSize, 491 deregisterFrameWrapper); 492 #else 493 return deregisterFrameWrapper(EHFrameSectionAddr); 494 #endif 495 } 496 497 EHFrameRegistrar::~EHFrameRegistrar() {} 498 499 InProcessEHFrameRegistrar &InProcessEHFrameRegistrar::getInstance() { 500 static InProcessEHFrameRegistrar Instance; 501 return Instance; 502 } 503 504 InProcessEHFrameRegistrar::InProcessEHFrameRegistrar() {} 505 506 LinkGraphPassFunction 507 createEHFrameRecorderPass(const Triple &TT, 508 StoreFrameRangeFunction StoreRangeAddress) { 509 const char *EHFrameSectionName = nullptr; 510 if (TT.getObjectFormat() == Triple::MachO) 511 EHFrameSectionName = "__eh_frame"; 512 else 513 EHFrameSectionName = ".eh_frame"; 514 515 auto RecordEHFrame = 516 [EHFrameSectionName, 517 StoreFrameRange = std::move(StoreRangeAddress)](LinkGraph &G) -> Error { 518 // Search for a non-empty eh-frame and record the address of the first 519 // symbol in it. 520 JITTargetAddress Addr = 0; 521 size_t Size = 0; 522 if (auto *S = G.findSectionByName(EHFrameSectionName)) { 523 auto R = SectionRange(*S); 524 Addr = R.getStart(); 525 Size = R.getSize(); 526 } 527 if (Addr == 0 && Size != 0) 528 return make_error<JITLinkError>("__eh_frame section can not have zero " 529 "address with non-zero size"); 530 StoreFrameRange(Addr, Size); 531 return Error::success(); 532 }; 533 534 return RecordEHFrame; 535 } 536 537 } // end namespace jitlink 538 } // end namespace llvm 539