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