LLVM  10.0.0svn
EHFrameSupport.cpp
Go to the documentation of this file.
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 
14 
15 #define DEBUG_TYPE "jitlink"
16 
17 namespace llvm {
18 namespace jitlink {
19 
21  StringRef EHFrameContent,
22  unsigned PointerSize,
24  : EHFrameAddress(EHFrameAddress), EHFrameContent(EHFrameContent),
25  PointerSize(PointerSize), EHFrameReader(EHFrameContent, Endianness) {}
26 
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 
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 !=
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) {
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 =
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 =
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,
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,
492 #else
493  return deregisterFrameWrapper(EHFrameSectionAddr);
494 #endif
495 }
496 
498 
500  static InProcessEHFrameRegistrar Instance;
501  return Instance;
502 }
503 
504 InProcessEHFrameRegistrar::InProcessEHFrameRegistrar() {}
505 
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
static void * SearchForAddressOfSymbol(const char *symbolName)
This function will search through all previously loaded dynamic libraries for the symbol symbolName...
This class represents lattice values for constants.
Definition: AllocatorList.h:23
Error readInteger(T &Dest)
Read an integer of the specified endianness into Dest and update the stream&#39;s offset.
format_object< Ts... > format(const char *Fmt, const Ts &... Vals)
These are helper functions used to produce formatted output.
Definition: Format.h:124
auto formatv(const char *Fmt, Ts &&... Vals) -> formatv_object< decltype(std::make_tuple(detail::build_format_adapter(std::forward< Ts >(Vals))...))>
constexpr support::endianness Endianness
The endianness of all multi-byte encoded values in MessagePack.
Definition: MsgPack.h:24
static void __register_frame(void *p)
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
Definition: Twine.h:80
Tagged union holding either a T or a Error.
Definition: yaml2obj.h:21
static void __deregister_frame(void *p)
uint64_t JITTargetAddress
Represents an address in the target process&#39;s address space.
Definition: JITSymbol.h:41
#define P(N)
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
Triple - Helper class for working with autoconf configuration names.
Definition: Triple.h:43
void setOffset(uint32_t Off)
static ErrorSuccess success()
Create a success value.
Definition: Error.h:326
Align max(MaybeAlign Lhs, Align Rhs)
Definition: Alignment.h:389
const DataFlowGraph & G
Definition: RDFGraph.cpp:202
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition: Debug.cpp:132
This file contains constants used for implementing Dwarf debug support.
ObjectFormatType getObjectFormat() const
getFormat - Get the object format for this triple.
Definition: Triple.h:326
#define I(x, y, z)
Definition: MD5.cpp:58
uint32_t Size
Definition: Profile.cpp:46
uint32_t bytesRemaining() const
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
Lightweight error class with error context and mandatory checking.
Definition: Error.h:157
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:48
#define LLVM_DEBUG(X)
Definition: Debug.h:122
const uint64_t Version
Definition: InstrProf.h:980