1 //===-------- JITLink_EHFrameSupport.cpp - JITLink eh-frame utils ---------===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 #include "EHFrameSupportImpl.h"
12 #include "llvm/BinaryFormat/Dwarf.h"
13 #include "llvm/Support/DynamicLibrary.h"
15 #define DEBUG_TYPE "jitlink"
20 EHFrameBinaryParser::EHFrameBinaryParser(JITTargetAddress EHFrameAddress
,
21 StringRef EHFrameContent
,
23 support::endianness Endianness
)
24 : EHFrameAddress(EHFrameAddress
), EHFrameContent(EHFrameContent
),
25 PointerSize(PointerSize
), EHFrameReader(EHFrameContent
, Endianness
) {}
27 Error
EHFrameBinaryParser::addToGraph() {
28 while (!EHFrameReader
.empty()) {
29 size_t RecordOffset
= EHFrameReader
.getOffset();
32 dbgs() << "Processing eh-frame record at "
33 << format("0x%016" PRIx64
, EHFrameAddress
+ RecordOffset
)
34 << " (offset " << RecordOffset
<< ")\n";
37 size_t RecordLength
= 0;
38 uint32_t RecordLengthField
;
39 if (auto Err
= EHFrameReader
.readInteger(RecordLengthField
))
42 // Process CIE/FDE length/extended-length fields to build the blocks.
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.
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
))
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;
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;
69 LLVM_DEBUG(dbgs() << " length: " << RecordLength
<< "\n");
71 // Read the CIE Pointer.
72 size_t CIEPointerAddress
= EHFrameAddress
+ EHFrameReader
.getOffset();
74 if (auto Err
= EHFrameReader
.readInteger(CIEPointer
))
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
))
82 if (auto Err
= processFDE(RecordOffset
, RecordLength
, CIEPointerAddress
,
87 EHFrameReader
.setOffset(RecordOffset
+ RecordLength
);
90 return Error::success();
93 void EHFrameBinaryParser::anchor() {}
95 Expected
<EHFrameBinaryParser::AugmentationInfo
>
96 EHFrameBinaryParser::parseAugmentationString() {
97 AugmentationInfo AugInfo
;
99 uint8_t *NextField
= &AugInfo
.Fields
[0];
101 if (auto Err
= EHFrameReader
.readInteger(NextChar
))
102 return std::move(Err
);
104 while (NextChar
!= 0) {
107 AugInfo
.AugmentationDataPresent
= true;
110 if (auto Err
= EHFrameReader
.readInteger(NextChar
))
111 return std::move(Err
);
113 return make_error
<JITLinkError
>("Unrecognized substring e" +
115 " in augmentation string");
116 AugInfo
.EHDataFieldPresent
= true;
121 *NextField
++ = NextChar
;
124 return make_error
<JITLinkError
>("Unrecognized character " +
126 " in augmentation string");
129 if (auto Err
= EHFrameReader
.readInteger(NextChar
))
130 return std::move(Err
);
133 return std::move(AugInfo
);
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) {
145 if (auto Err
= EHFrameReader
.readInteger(Addr32
))
146 return std::move(Err
);
149 llvm_unreachable("Pointer size is not 32-bit or 64-bit");
153 Error
EHFrameBinaryParser::processCIE(size_t RecordOffset
,
154 size_t RecordLength
) {
155 // Use the dwarf namespace for convenient access to pointer encoding
157 using namespace dwarf
;
159 LLVM_DEBUG(dbgs() << " Record is CIE\n");
162 createCIERecord(EHFrameAddress
+ RecordOffset
,
163 EHFrameContent
.substr(RecordOffset
, RecordLength
));
165 CIEInformation
CIEInfo(CIESymbol
);
168 if (auto Err
= EHFrameReader
.readInteger(Version
))
172 return make_error
<JITLinkError
>("Bad CIE version " + Twine(Version
) +
173 " (should be 0x01) in eh-frame");
175 auto AugInfo
= parseAugmentationString();
177 return AugInfo
.takeError();
179 // Skip the EH Data field if present.
180 if (AugInfo
->EHDataFieldPresent
)
181 if (auto Err
= EHFrameReader
.skip(PointerSize
))
184 // Read and sanity check the code alignment factor.
186 uint64_t CodeAlignmentFactor
= 0;
187 if (auto Err
= EHFrameReader
.readULEB128(CodeAlignmentFactor
))
189 if (CodeAlignmentFactor
!= 1)
190 return make_error
<JITLinkError
>("Unsupported CIE code alignment factor " +
191 Twine(CodeAlignmentFactor
) +
195 // Read and sanity check the data alignment factor.
197 int64_t DataAlignmentFactor
= 0;
198 if (auto Err
= EHFrameReader
.readSLEB128(DataAlignmentFactor
))
200 if (DataAlignmentFactor
!= -8)
201 return make_error
<JITLinkError
>("Unsupported CIE data alignment factor " +
202 Twine(DataAlignmentFactor
) +
206 // Skip the return address register field.
207 if (auto Err
= EHFrameReader
.skip(1))
210 uint64_t AugmentationDataLength
= 0;
211 if (auto Err
= EHFrameReader
.readULEB128(AugmentationDataLength
))
214 uint32_t AugmentationDataStartOffset
= EHFrameReader
.getOffset();
216 uint8_t *NextField
= &AugInfo
->Fields
[0];
217 while (uint8_t Field
= *NextField
++) {
220 CIEInfo
.FDEsHaveLSDAField
= true;
221 uint8_t LSDAPointerEncoding
;
222 if (auto Err
= EHFrameReader
.readInteger(LSDAPointerEncoding
))
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()));
232 uint8_t PersonalityPointerEncoding
= 0;
233 if (auto Err
= EHFrameReader
.readInteger(PersonalityPointerEncoding
))
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 "
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
))
248 uint8_t FDEPointerEncoding
;
249 if (auto Err
= EHFrameReader
.readInteger(FDEPointerEncoding
))
251 if (FDEPointerEncoding
!= (DW_EH_PE_pcrel
| DW_EH_PE_absptr
))
252 return make_error
<JITLinkError
>(
253 "Unsupported FDE address pointer "
255 formatv("{0:x2}", FDEPointerEncoding
) + " in CIE at " +
256 formatv("{0:x16}", CIESymbol
.getAddress()));
260 llvm_unreachable("Invalid augmentation string field");
264 if (EHFrameReader
.getOffset() - AugmentationDataStartOffset
>
265 AugmentationDataLength
)
266 return make_error
<JITLinkError
>("Read past the end of the augmentation "
267 "data while parsing fields");
269 assert(!CIEInfos
.count(CIESymbol
.getAddress()) &&
270 "Multiple CIEs recorded at the same address?");
271 CIEInfos
[CIESymbol
.getAddress()] = std::move(CIEInfo
);
273 return Error::success();
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");
282 dbgs() << " CIE pointer: "
283 << format("0x%016" PRIx64
, CIEPointerAddress
- CIEPointer
) << "\n";
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
;
294 // Read and sanity check the PC-start pointer and size.
295 JITTargetAddress PCBeginAddress
= EHFrameAddress
+ EHFrameReader
.getOffset();
297 auto PCBeginDelta
= readAbsolutePointer();
299 return PCBeginDelta
.takeError();
301 JITTargetAddress PCBegin
= PCBeginAddress
+ *PCBeginDelta
;
303 dbgs() << " PC begin: " << format("0x%016" PRIx64
, PCBegin
) << "\n";
306 auto *TargetSymbol
= getSymbolAtAddress(PCBegin
);
309 return make_error
<JITLinkError
>("FDE PC-begin " +
310 formatv("{0:x16}", PCBegin
) +
311 " does not point at symbol");
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()));
319 LLVM_DEBUG(dbgs() << " FDE target: " << *TargetSymbol
<< "\n");
321 // Skip over the PC range size field.
322 if (auto Err
= EHFrameReader
.skip(PointerSize
))
325 Symbol
*LSDASymbol
= nullptr;
326 JITTargetAddress LSDAAddress
= 0;
327 if (CIEInfo
.FDEsHaveLSDAField
) {
328 uint64_t AugmentationDataSize
;
329 if (auto Err
= EHFrameReader
.readULEB128(AugmentationDataSize
))
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();
339 return LSDADelta
.takeError();
341 JITTargetAddress LSDA
= LSDAAddress
+ *LSDADelta
;
343 LSDASymbol
= getSymbolAtAddress(LSDA
);
346 return make_error
<JITLinkError
>("FDE LSDA " + formatv("{0:x16}", LSDA
) +
347 " does not point at symbol");
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()));
355 LLVM_DEBUG(dbgs() << " FDE LSDA: " << *LSDASymbol
<< "\n");
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
);
364 return FDESymbol
.takeError();
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
373 #define HAVE_EHTABLE_SUPPORT 0
376 #if HAVE_EHTABLE_SUPPORT
377 extern "C" void __register_frame(const void *);
378 extern "C" void __deregister_frame(const void *);
380 Error
registerFrameWrapper(const void *P
) {
382 return Error::success();
385 Error
deregisterFrameWrapper(const void *P
) {
386 __deregister_frame(P
);
387 return Error::success();
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;
400 *(void **)&RegisterFrame
=
401 llvm::sys::DynamicLibrary::SearchForAddressOfSymbol("__register_frame");
405 return Error::success();
408 return make_error
<JITLinkError
>("could not register eh-frame: "
409 "__register_frame function not found");
412 static Error
deregisterFrameWrapper(const void *P
) {
413 static void((*DeregisterFrame
)(const void *)) = 0;
415 if (!DeregisterFrame
)
416 *(void **)&DeregisterFrame
=
417 llvm::sys::DynamicLibrary::SearchForAddressOfSymbol(
418 "__deregister_frame");
420 if (DeregisterFrame
) {
422 return Error::success();
425 return make_error
<JITLinkError
>("could not deregister eh-frame: "
426 "__deregister_frame function not found");
432 template <typename HandleFDEFn
>
433 Error
walkAppleEHFrameSection(const char *const SectionStart
,
435 HandleFDEFn HandleFDE
) {
436 const char *CurCFIRecord
= SectionStart
;
437 const char *End
= SectionStart
+ SectionSize
;
438 uint64_t Size
= *reinterpret_cast<const uint32_t *>(CurCFIRecord
);
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;
446 uint32_t Offset
= *reinterpret_cast<const uint32_t *>(OffsetField
);
448 if (auto Err
= HandleFDE(CurCFIRecord
))
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
));
459 CurCFIRecord
+= Size
;
461 Size
= *reinterpret_cast<const uint32_t *>(CurCFIRecord
);
464 return Error::success();
469 Error
registerEHFrameSection(const void *EHFrameSectionAddr
,
470 size_t EHFrameSectionSize
) {
472 // On Darwin __register_frame has to be called for each FDE entry.
473 return walkAppleEHFrameSection(static_cast<const char *>(EHFrameSectionAddr
),
475 registerFrameWrapper
);
477 // On Linux __register_frame takes a single argument:
478 // a pointer to the start of the .eh_frame section.
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
);
486 Error
deregisterEHFrameSection(const void *EHFrameSectionAddr
,
487 size_t EHFrameSectionSize
) {
489 return walkAppleEHFrameSection(static_cast<const char *>(EHFrameSectionAddr
),
491 deregisterFrameWrapper
);
493 return deregisterFrameWrapper(EHFrameSectionAddr
);
497 EHFrameRegistrar::~EHFrameRegistrar() {}
499 InProcessEHFrameRegistrar
&InProcessEHFrameRegistrar::getInstance() {
500 static InProcessEHFrameRegistrar Instance
;
504 InProcessEHFrameRegistrar::InProcessEHFrameRegistrar() {}
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";
513 EHFrameSectionName
= ".eh_frame";
517 StoreFrameRange
= std::move(StoreRangeAddress
)](LinkGraph
&G
) -> Error
{
518 // Search for a non-empty eh-frame and record the address of the first
520 JITTargetAddress Addr
= 0;
522 if (auto *S
= G
.findSectionByName(EHFrameSectionName
)) {
523 auto R
= SectionRange(*S
);
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();
534 return RecordEHFrame
;
537 } // end namespace jitlink
538 } // end namespace llvm