LLVM  15.0.0git
EHFrameSupport.cpp
Go to the documentation of this file.
1 //===-------- JITLink_EHFrameSupport.cpp - JITLink eh-frame utils ---------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #include "EHFrameSupportImpl.h"
10 
12 #include "llvm/Config/config.h"
16 
17 #define DEBUG_TYPE "jitlink"
18 
19 namespace llvm {
20 namespace jitlink {
21 
26  : EHFrameSectionName(EHFrameSectionName), PointerSize(PointerSize),
29 
31  auto *EHFrame = G.findSectionByName(EHFrameSectionName);
32 
33  if (!EHFrame) {
34  LLVM_DEBUG({
35  dbgs() << "EHFrameEdgeFixer: No " << EHFrameSectionName
36  << " section. Nothing to do\n";
37  });
38  return Error::success();
39  }
40 
41  // Check that we support the graph's pointer size.
42  if (G.getPointerSize() != 4 && G.getPointerSize() != 8)
43  return make_error<JITLinkError>(
44  "EHFrameEdgeFixer only supports 32 and 64 bit targets");
45 
46  LLVM_DEBUG({
47  dbgs() << "EHFrameEdgeFixer: Processing " << EHFrameSectionName << "...\n";
48  });
49 
50  ParseContext PC(G);
51 
52  // Build a map of all blocks and symbols in the text sections. We will use
53  // these for finding / building edge targets when processing FDEs.
54  for (auto &Sec : G.sections()) {
55  // Just record the most-canonical symbol (for eh-frame purposes) at each
56  // address.
57  for (auto *Sym : Sec.symbols()) {
58  auto &CurSym = PC.AddrToSym[Sym->getAddress()];
59  if (!CurSym || (std::make_tuple(Sym->getLinkage(), Sym->getScope(),
60  !Sym->hasName(), Sym->getName()) <
61  std::make_tuple(CurSym->getLinkage(), CurSym->getScope(),
62  !CurSym->hasName(), CurSym->getName())))
63  CurSym = Sym;
64  }
65  if (auto Err = PC.AddrToBlock.addBlocks(Sec.blocks(),
67  return Err;
68  }
69 
70  // Sort eh-frame blocks into address order to ensure we visit CIEs before
71  // their child FDEs.
72  std::vector<Block *> EHFrameBlocks;
73  for (auto *B : EHFrame->blocks())
74  EHFrameBlocks.push_back(B);
75  llvm::sort(EHFrameBlocks, [](const Block *LHS, const Block *RHS) {
76  return LHS->getAddress() < RHS->getAddress();
77  });
78 
79  // Loop over the blocks in address order.
80  for (auto *B : EHFrameBlocks)
81  if (auto Err = processBlock(PC, *B))
82  return Err;
83 
84  return Error::success();
85 }
86 
87 Error EHFrameEdgeFixer::processBlock(ParseContext &PC, Block &B) {
88 
89  LLVM_DEBUG(dbgs() << " Processing block at " << B.getAddress() << "\n");
90 
91  // eh-frame should not contain zero-fill blocks.
92  if (B.isZeroFill())
93  return make_error<JITLinkError>("Unexpected zero-fill block in " +
94  EHFrameSectionName + " section");
95 
96  if (B.getSize() == 0) {
97  LLVM_DEBUG(dbgs() << " Block is empty. Skipping.\n");
98  return Error::success();
99  }
100 
101  // Find the offsets of any existing edges from this block.
102  BlockEdgeMap BlockEdges;
103  for (auto &E : B.edges())
104  if (E.isRelocation()) {
105  if (BlockEdges.count(E.getOffset()))
106  return make_error<JITLinkError>(
107  "Multiple relocations at offset " +
108  formatv("{0:x16}", E.getOffset()) + " in " + EHFrameSectionName +
109  " block at address " + formatv("{0:x16}", B.getAddress()));
110 
111  BlockEdges[E.getOffset()] = EdgeTarget(E);
112  }
113 
114  CIEInfosMap CIEInfos;
115  BinaryStreamReader BlockReader(
116  StringRef(B.getContent().data(), B.getContent().size()),
117  PC.G.getEndianness());
118  while (!BlockReader.empty()) {
119  size_t RecordStartOffset = BlockReader.getOffset();
120 
121  LLVM_DEBUG({
122  dbgs() << " Processing CFI record at "
123  << (B.getAddress() + RecordStartOffset) << "\n";
124  });
125 
126  // Get the record length.
127  size_t RecordRemaining;
128  {
129  uint32_t Length;
130  if (auto Err = BlockReader.readInteger(Length))
131  return Err;
132  // If Length < 0xffffffff then use the regular length field, otherwise
133  // read the extended length field.
134  if (Length != 0xffffffff)
135  RecordRemaining = Length;
136  else {
137  uint64_t ExtendedLength;
138  if (auto Err = BlockReader.readInteger(ExtendedLength))
139  return Err;
140  RecordRemaining = ExtendedLength;
141  }
142  }
143 
144  if (BlockReader.bytesRemaining() < RecordRemaining)
145  return make_error<JITLinkError>(
146  "Incomplete CFI record at " +
147  formatv("{0:x16}", B.getAddress() + RecordStartOffset));
148 
149  // Read the CIE delta for this record.
150  uint64_t CIEDeltaFieldOffset = BlockReader.getOffset() - RecordStartOffset;
151  uint32_t CIEDelta;
152  if (auto Err = BlockReader.readInteger(CIEDelta))
153  return Err;
154 
155  if (CIEDelta == 0) {
156  if (auto Err = processCIE(PC, B, RecordStartOffset,
157  CIEDeltaFieldOffset + RecordRemaining,
158  CIEDeltaFieldOffset, BlockEdges))
159  return Err;
160  } else {
161  if (auto Err = processFDE(PC, B, RecordStartOffset,
162  CIEDeltaFieldOffset + RecordRemaining,
163  CIEDeltaFieldOffset, CIEDelta, BlockEdges))
164  return Err;
165  }
166 
167  // Move to the next record.
168  BlockReader.setOffset(RecordStartOffset + CIEDeltaFieldOffset +
169  RecordRemaining);
170  }
171 
172  return Error::success();
173 }
174 
175 Error EHFrameEdgeFixer::processCIE(ParseContext &PC, Block &B,
176  size_t RecordOffset, size_t RecordLength,
177  size_t CIEDeltaFieldOffset,
178  const BlockEdgeMap &BlockEdges) {
179 
180  LLVM_DEBUG(dbgs() << " Record is CIE\n");
181 
182  auto RecordContent = B.getContent().slice(RecordOffset, RecordLength);
183  BinaryStreamReader RecordReader(
184  StringRef(RecordContent.data(), RecordContent.size()),
185  PC.G.getEndianness());
186 
187  // Skip past the CIE delta field: we've already processed this far.
188  RecordReader.setOffset(CIEDeltaFieldOffset + 4);
189 
190  auto &CIESymbol =
191  PC.G.addAnonymousSymbol(B, RecordOffset, RecordLength, false, false);
192  CIEInformation CIEInfo(CIESymbol);
193 
194  uint8_t Version = 0;
195  if (auto Err = RecordReader.readInteger(Version))
196  return Err;
197 
198  if (Version != 0x01)
199  return make_error<JITLinkError>("Bad CIE version " + Twine(Version) +
200  " (should be 0x01) in eh-frame");
201 
202  auto AugInfo = parseAugmentationString(RecordReader);
203  if (!AugInfo)
204  return AugInfo.takeError();
205 
206  // Skip the EH Data field if present.
207  if (AugInfo->EHDataFieldPresent)
208  if (auto Err = RecordReader.skip(PC.G.getPointerSize()))
209  return Err;
210 
211  // Read and validate the code alignment factor.
212  {
213  uint64_t CodeAlignmentFactor = 0;
214  if (auto Err = RecordReader.readULEB128(CodeAlignmentFactor))
215  return Err;
216  if (CodeAlignmentFactor != 1)
217  return make_error<JITLinkError>("Unsupported CIE code alignment factor " +
218  Twine(CodeAlignmentFactor) +
219  " (expected 1)");
220  }
221 
222  // Read and validate the data alignment factor.
223  {
224  int64_t DataAlignmentFactor = 0;
225  if (auto Err = RecordReader.readSLEB128(DataAlignmentFactor))
226  return Err;
227  if (DataAlignmentFactor != -8)
228  return make_error<JITLinkError>("Unsupported CIE data alignment factor " +
229  Twine(DataAlignmentFactor) +
230  " (expected -8)");
231  }
232 
233  // Skip the return address register field.
234  if (auto Err = RecordReader.skip(1))
235  return Err;
236 
237  if (AugInfo->AugmentationDataPresent) {
238 
239  CIEInfo.AugmentationDataPresent = true;
240 
241  uint64_t AugmentationDataLength = 0;
242  if (auto Err = RecordReader.readULEB128(AugmentationDataLength))
243  return Err;
244 
245  uint32_t AugmentationDataStartOffset = RecordReader.getOffset();
246 
247  uint8_t *NextField = &AugInfo->Fields[0];
248  while (uint8_t Field = *NextField++) {
249  switch (Field) {
250  case 'L':
251  CIEInfo.LSDAPresent = true;
252  if (auto PE = readPointerEncoding(RecordReader, B, "LSDA"))
253  CIEInfo.LSDAEncoding = *PE;
254  else
255  return PE.takeError();
256  break;
257  case 'P': {
258  auto PersonalityPointerEncoding =
259  readPointerEncoding(RecordReader, B, "personality");
260  if (!PersonalityPointerEncoding)
261  return PersonalityPointerEncoding.takeError();
262  if (auto Err =
263  getOrCreateEncodedPointerEdge(
264  PC, BlockEdges, *PersonalityPointerEncoding, RecordReader,
265  B, RecordOffset + RecordReader.getOffset(), "personality")
266  .takeError())
267  return Err;
268  break;
269  }
270  case 'R':
271  if (auto PE = readPointerEncoding(RecordReader, B, "address")) {
272  CIEInfo.AddressEncoding = *PE;
273  if (CIEInfo.AddressEncoding == dwarf::DW_EH_PE_omit)
274  return make_error<JITLinkError>(
275  "Invalid address encoding DW_EH_PE_omit in CIE at " +
276  formatv("{0:x}", (B.getAddress() + RecordOffset).getValue()));
277  } else
278  return PE.takeError();
279  break;
280  default:
281  llvm_unreachable("Invalid augmentation string field");
282  }
283  }
284 
285  if (RecordReader.getOffset() - AugmentationDataStartOffset >
286  AugmentationDataLength)
287  return make_error<JITLinkError>("Read past the end of the augmentation "
288  "data while parsing fields");
289  }
290 
291  assert(!PC.CIEInfos.count(CIESymbol.getAddress()) &&
292  "Multiple CIEs recorded at the same address?");
293  PC.CIEInfos[CIESymbol.getAddress()] = std::move(CIEInfo);
294 
295  return Error::success();
296 }
297 
298 Error EHFrameEdgeFixer::processFDE(ParseContext &PC, Block &B,
299  size_t RecordOffset, size_t RecordLength,
300  size_t CIEDeltaFieldOffset,
301  uint32_t CIEDelta,
302  const BlockEdgeMap &BlockEdges) {
303  LLVM_DEBUG(dbgs() << " Record is FDE\n");
304 
305  orc::ExecutorAddr RecordAddress = B.getAddress() + RecordOffset;
306 
307  auto RecordContent = B.getContent().slice(RecordOffset, RecordLength);
308  BinaryStreamReader RecordReader(
309  StringRef(RecordContent.data(), RecordContent.size()),
310  PC.G.getEndianness());
311 
312  // Skip past the CIE delta field: we've already read this far.
313  RecordReader.setOffset(CIEDeltaFieldOffset + 4);
314 
315  auto &FDESymbol =
316  PC.G.addAnonymousSymbol(B, RecordOffset, RecordLength, false, false);
317 
318  CIEInformation *CIEInfo = nullptr;
319 
320  {
321  // Process the CIE pointer field.
322  auto CIEEdgeItr = BlockEdges.find(RecordOffset + CIEDeltaFieldOffset);
323  orc::ExecutorAddr CIEAddress =
324  RecordAddress + orc::ExecutorAddrDiff(CIEDeltaFieldOffset) -
325  orc::ExecutorAddrDiff(CIEDelta);
326  if (CIEEdgeItr == BlockEdges.end()) {
327 
328  LLVM_DEBUG({
329  dbgs() << " Adding edge at "
330  << (RecordAddress + CIEDeltaFieldOffset)
331  << " to CIE at: " << CIEAddress << "\n";
332  });
333  if (auto CIEInfoOrErr = PC.findCIEInfo(CIEAddress))
334  CIEInfo = *CIEInfoOrErr;
335  else
336  return CIEInfoOrErr.takeError();
337  assert(CIEInfo->CIESymbol && "CIEInfo has no CIE symbol set");
338  B.addEdge(NegDelta32, RecordOffset + CIEDeltaFieldOffset,
339  *CIEInfo->CIESymbol, 0);
340  } else {
341  LLVM_DEBUG({
342  dbgs() << " Already has edge at "
343  << (RecordAddress + CIEDeltaFieldOffset) << " to CIE at "
344  << CIEAddress << "\n";
345  });
346  auto &EI = CIEEdgeItr->second;
347  if (EI.Addend)
348  return make_error<JITLinkError>(
349  "CIE edge at " +
350  formatv("{0:x16}", RecordAddress + CIEDeltaFieldOffset) +
351  " has non-zero addend");
352  if (auto CIEInfoOrErr = PC.findCIEInfo(EI.Target->getAddress()))
353  CIEInfo = *CIEInfoOrErr;
354  else
355  return CIEInfoOrErr.takeError();
356  }
357  }
358 
359  // Process the PC-Begin field.
360  LLVM_DEBUG({
361  dbgs() << " Processing PC-begin at "
362  << (RecordAddress + RecordReader.getOffset()) << "\n";
363  });
364  if (auto PCBegin = getOrCreateEncodedPointerEdge(
365  PC, BlockEdges, CIEInfo->AddressEncoding, RecordReader, B,
366  RecordReader.getOffset(), "PC begin")) {
367  assert(*PCBegin && "PC-begin symbol not set");
368  // Add a keep-alive edge from the FDE target to the FDE to ensure that the
369  // FDE is kept alive if its target is.
370  LLVM_DEBUG({
371  dbgs() << " Adding keep-alive edge from target at "
372  << (*PCBegin)->getBlock().getAddress() << " to FDE at "
373  << RecordAddress << "\n";
374  });
375  (*PCBegin)->getBlock().addEdge(Edge::KeepAlive, 0, FDESymbol, 0);
376  } else
377  return PCBegin.takeError();
378 
379  // Skip over the PC range size field.
380  if (auto Err = skipEncodedPointer(CIEInfo->AddressEncoding, RecordReader))
381  return Err;
382 
383  if (CIEInfo->AugmentationDataPresent) {
384  uint64_t AugmentationDataSize;
385  if (auto Err = RecordReader.readULEB128(AugmentationDataSize))
386  return Err;
387 
388  if (CIEInfo->LSDAPresent)
389  if (auto Err = getOrCreateEncodedPointerEdge(
390  PC, BlockEdges, CIEInfo->LSDAEncoding, RecordReader, B,
391  RecordReader.getOffset(), "LSDA")
392  .takeError())
393  return Err;
394  } else {
395  LLVM_DEBUG(dbgs() << " Record does not have LSDA field.\n");
396  }
397 
398  return Error::success();
399 }
400 
401 Expected<EHFrameEdgeFixer::AugmentationInfo>
402 EHFrameEdgeFixer::parseAugmentationString(BinaryStreamReader &RecordReader) {
403  AugmentationInfo AugInfo;
404  uint8_t NextChar;
405  uint8_t *NextField = &AugInfo.Fields[0];
406 
407  if (auto Err = RecordReader.readInteger(NextChar))
408  return std::move(Err);
409 
410  while (NextChar != 0) {
411  switch (NextChar) {
412  case 'z':
413  AugInfo.AugmentationDataPresent = true;
414  break;
415  case 'e':
416  if (auto Err = RecordReader.readInteger(NextChar))
417  return std::move(Err);
418  if (NextChar != 'h')
419  return make_error<JITLinkError>("Unrecognized substring e" +
420  Twine(NextChar) +
421  " in augmentation string");
422  AugInfo.EHDataFieldPresent = true;
423  break;
424  case 'L':
425  case 'P':
426  case 'R':
427  *NextField++ = NextChar;
428  break;
429  default:
430  return make_error<JITLinkError>("Unrecognized character " +
431  Twine(NextChar) +
432  " in augmentation string");
433  }
434 
435  if (auto Err = RecordReader.readInteger(NextChar))
436  return std::move(Err);
437  }
438 
439  return std::move(AugInfo);
440 }
441 
442 Expected<uint8_t> EHFrameEdgeFixer::readPointerEncoding(BinaryStreamReader &R,
443  Block &InBlock,
444  const char *FieldName) {
445  using namespace dwarf;
446 
447  uint8_t PointerEncoding;
448  if (auto Err = R.readInteger(PointerEncoding))
449  return std::move(Err);
450 
451  bool Supported = true;
452  switch (PointerEncoding & 0xf) {
453  case DW_EH_PE_uleb128:
454  case DW_EH_PE_udata2:
455  case DW_EH_PE_sleb128:
456  case DW_EH_PE_sdata2:
457  Supported = false;
458  break;
459  }
460  if (Supported) {
461  switch (PointerEncoding & 0x70) {
462  case DW_EH_PE_textrel:
463  case DW_EH_PE_datarel:
464  case DW_EH_PE_funcrel:
465  case DW_EH_PE_aligned:
466  Supported = false;
467  break;
468  }
469  }
470 
471  if (Supported)
472  return PointerEncoding;
473 
474  return make_error<JITLinkError>("Unsupported pointer encoding " +
475  formatv("{0:x2}", PointerEncoding) + " for " +
476  FieldName + "in CFI record at " +
477  formatv("{0:x16}", InBlock.getAddress()));
478 }
479 
480 Error EHFrameEdgeFixer::skipEncodedPointer(uint8_t PointerEncoding,
481  BinaryStreamReader &RecordReader) {
482  using namespace dwarf;
483 
484  // Switch absptr to corresponding udata encoding.
485  if ((PointerEncoding & 0xf) == DW_EH_PE_absptr)
486  PointerEncoding |= (PointerSize == 8) ? DW_EH_PE_udata8 : DW_EH_PE_udata4;
487 
488  switch (PointerEncoding & 0xf) {
489  case DW_EH_PE_udata4:
490  case DW_EH_PE_sdata4:
491  if (auto Err = RecordReader.skip(4))
492  return Err;
493  break;
494  case DW_EH_PE_udata8:
495  case DW_EH_PE_sdata8:
496  if (auto Err = RecordReader.skip(8))
497  return Err;
498  break;
499  default:
500  llvm_unreachable("Unrecognized encoding");
501  }
502  return Error::success();
503 }
504 
505 Expected<Symbol *> EHFrameEdgeFixer::getOrCreateEncodedPointerEdge(
506  ParseContext &PC, const BlockEdgeMap &BlockEdges, uint8_t PointerEncoding,
507  BinaryStreamReader &RecordReader, Block &BlockToFix,
508  size_t PointerFieldOffset, const char *FieldName) {
509  using namespace dwarf;
510 
511  if (PointerEncoding == DW_EH_PE_omit)
512  return nullptr;
513 
514  // If there's already an edge here then just skip the encoded pointer and
515  // return the edge's target.
516  {
517  auto EdgeI = BlockEdges.find(PointerFieldOffset);
518  if (EdgeI != BlockEdges.end()) {
519  LLVM_DEBUG({
520  dbgs() << " Existing edge at "
521  << (BlockToFix.getAddress() + PointerFieldOffset) << " to "
522  << FieldName << " at " << EdgeI->second.Target->getAddress();
523  if (EdgeI->second.Target->hasName())
524  dbgs() << " (" << EdgeI->second.Target->getName() << ")";
525  dbgs() << "\n";
526  });
527  if (auto Err = skipEncodedPointer(PointerEncoding, RecordReader))
528  return std::move(Err);
529  return EdgeI->second.Target;
530  }
531  }
532 
533  // Switch absptr to corresponding udata encoding.
534  if ((PointerEncoding & 0xf) == DW_EH_PE_absptr)
535  PointerEncoding |= (PointerSize == 8) ? DW_EH_PE_udata8 : DW_EH_PE_udata4;
536 
537  // We need to create an edge. Start by reading the field value.
538  uint64_t FieldValue;
539  bool Is64Bit = false;
540  switch (PointerEncoding & 0xf) {
541  case DW_EH_PE_udata4: {
542  uint32_t Val;
543  if (auto Err = RecordReader.readInteger(Val))
544  return std::move(Err);
545  FieldValue = Val;
546  break;
547  }
548  case DW_EH_PE_sdata4: {
549  uint32_t Val;
550  if (auto Err = RecordReader.readInteger(Val))
551  return std::move(Err);
552  FieldValue = Val;
553  break;
554  }
555  case DW_EH_PE_udata8:
556  case DW_EH_PE_sdata8:
557  Is64Bit = true;
558  if (auto Err = RecordReader.readInteger(FieldValue))
559  return std::move(Err);
560  break;
561  default:
562  llvm_unreachable("Unsupported encoding");
563  }
564 
565  // Find the edge target and edge kind to use.
566  orc::ExecutorAddr Target;
567  Edge::Kind PtrEdgeKind = Edge::Invalid;
568  if ((PointerEncoding & 0x70) == DW_EH_PE_pcrel) {
569  Target = BlockToFix.getAddress() + PointerFieldOffset;
570  PtrEdgeKind = Is64Bit ? Delta64 : Delta32;
571  } else
572  PtrEdgeKind = Is64Bit ? Pointer64 : Pointer32;
573  Target += FieldValue;
574 
575  // Find or create a symbol to point the edge at.
576  auto TargetSym = getOrCreateSymbol(PC, Target);
577  if (!TargetSym)
578  return TargetSym.takeError();
579  BlockToFix.addEdge(PtrEdgeKind, PointerFieldOffset, *TargetSym, 0);
580 
581  LLVM_DEBUG({
582  dbgs() << " Adding edge at "
583  << (BlockToFix.getAddress() + PointerFieldOffset) << " to "
584  << FieldName << " at " << TargetSym->getAddress();
585  if (TargetSym->hasName())
586  dbgs() << " (" << TargetSym->getName() << ")";
587  dbgs() << "\n";
588  });
589 
590  return &*TargetSym;
591 }
592 
593 Expected<Symbol &> EHFrameEdgeFixer::getOrCreateSymbol(ParseContext &PC,
594  orc::ExecutorAddr Addr) {
595  // See whether we have a canonical symbol for the given address already.
596  auto CanonicalSymI = PC.AddrToSym.find(Addr);
597  if (CanonicalSymI != PC.AddrToSym.end())
598  return *CanonicalSymI->second;
599 
600  // Otherwise search for a block covering the address and create a new symbol.
601  auto *B = PC.AddrToBlock.getBlockCovering(Addr);
602  if (!B)
603  return make_error<JITLinkError>("No symbol or block covering address " +
604  formatv("{0:x16}", Addr));
605 
606  auto &S =
607  PC.G.addAnonymousSymbol(*B, Addr - B->getAddress(), 0, false, false);
608  PC.AddrToSym[S.getAddress()] = &S;
609  return S;
610 }
611 
612 char EHFrameNullTerminator::NullTerminatorBlockContent[4] = {0, 0, 0, 0};
613 
615  : EHFrameSectionName(EHFrameSectionName) {}
616 
618  auto *EHFrame = G.findSectionByName(EHFrameSectionName);
619 
620  if (!EHFrame)
621  return Error::success();
622 
623  LLVM_DEBUG({
624  dbgs() << "EHFrameNullTerminator adding null terminator to "
625  << EHFrameSectionName << "\n";
626  });
627 
628  auto &NullTerminatorBlock =
629  G.createContentBlock(*EHFrame, NullTerminatorBlockContent,
630  orc::ExecutorAddr(~uint64_t(4)), 1, 0);
631  G.addAnonymousSymbol(NullTerminatorBlock, 0, 4, false, true);
632  return Error::success();
633 }
634 
636 
638  orc::ExecutorAddrRange EHFrameSection) {
639  return orc::registerEHFrameSection(EHFrameSection.Start.toPtr<void *>(),
640  EHFrameSection.size());
641 }
642 
644  orc::ExecutorAddrRange EHFrameSection) {
645  return orc::deregisterEHFrameSection(EHFrameSection.Start.toPtr<void *>(),
646  EHFrameSection.size());
647 }
648 
651  StoreFrameRangeFunction StoreRangeAddress) {
652  const char *EHFrameSectionName = nullptr;
653  if (TT.getObjectFormat() == Triple::MachO)
654  EHFrameSectionName = "__TEXT,__eh_frame";
655  else
656  EHFrameSectionName = ".eh_frame";
657 
658  auto RecordEHFrame =
659  [EHFrameSectionName,
660  StoreFrameRange = std::move(StoreRangeAddress)](LinkGraph &G) -> Error {
661  // Search for a non-empty eh-frame and record the address of the first
662  // symbol in it.
664  size_t Size = 0;
665  if (auto *S = G.findSectionByName(EHFrameSectionName)) {
666  auto R = SectionRange(*S);
667  Addr = R.getStart();
668  Size = R.getSize();
669  }
670  if (!Addr && Size != 0)
671  return make_error<JITLinkError>(
672  StringRef(EHFrameSectionName) +
673  " section can not have zero address with non-zero size");
674  StoreFrameRange(Addr, Size);
675  return Error::success();
676  };
677 
678  return RecordEHFrame;
679 }
680 
681 } // end namespace jitlink
682 } // end namespace llvm
llvm::orc::ExecutorAddr
Represents an address in the executor process.
Definition: ExecutorAddress.h:30
llvm
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:17
llvm::dwarf::DW_EH_PE_sdata4
@ DW_EH_PE_sdata4
Definition: Dwarf.h:445
llvm::lltok::Error
@ Error
Definition: LLToken.h:21
llvm::Error::success
static ErrorSuccess success()
Create a success value.
Definition: Error.h:329
llvm::dwarf::DW_EH_PE_sdata8
@ DW_EH_PE_sdata8
Definition: Dwarf.h:446
llvm::Triple
Triple - Helper class for working with autoconf configuration names.
Definition: Triple.h:44
DynamicLibrary.h
llvm::orc::ExecutorAddr::toPtr
std::enable_if_t< std::is_pointer< T >::value, T > toPtr() const
Cast this ExecutorAddr to a pointer of the given type.
Definition: ExecutorAddress.h:47
llvm::orc::deregisterEHFrameSection
Error deregisterEHFrameSection(const void *EHFrameSectionAddr, size_t EHFrameSectionSize)
Unregister frames in the given eh-frame section with libunwind.
Definition: RegisterEHFrames.cpp:147
llvm::AMDGPU::Exp::Target
Target
Definition: SIDefines.h:851
RHS
Value * RHS
Definition: X86PartialReduction.cpp:76
llvm::dwarf::DW_EH_PE_textrel
@ DW_EH_PE_textrel
Definition: Dwarf.h:449
LLVM_DEBUG
#define LLVM_DEBUG(X)
Definition: Debug.h:101
llvm::RISCVFenceField::R
@ R
Definition: RISCVBaseInfo.h:240
llvm::dbgs
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition: Debug.cpp:163
LHS
Value * LHS
Definition: X86PartialReduction.cpp:75
llvm::formatv
auto formatv(const char *Fmt, Ts &&... Vals) -> formatv_object< decltype(std::make_tuple(detail::build_format_adapter(std::forward< Ts >(Vals))...))>
Definition: FormatVariadic.h:251
E
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
llvm::dwarf::DW_EH_PE_udata2
@ DW_EH_PE_udata2
Definition: Dwarf.h:440
B
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
llvm::orc::ExecutorAddrDiff
uint64_t ExecutorAddrDiff
Definition: ExecutorAddress.h:27
RegisterEHFrames.h
llvm::orc::ExecutorAddrRange
Represents an address range in the exceutor process.
Definition: ExecutorAddress.h:148
llvm::dwarf::DW_EH_PE_funcrel
@ DW_EH_PE_funcrel
Definition: Dwarf.h:451
llvm::dwarf::DW_EH_PE_udata4
@ DW_EH_PE_udata4
Definition: Dwarf.h:441
llvm::orc::ExecutorAddrRange::size
ExecutorAddrDiff size() const
Definition: ExecutorAddress.h:156
G
const DataFlowGraph & G
Definition: RDFGraph.cpp:200
InBlock
static bool InBlock(const Value *V, const BasicBlock *BB)
Definition: SelectionDAGBuilder.cpp:2144
llvm::dwarf::DW_EH_PE_udata8
@ DW_EH_PE_udata8
Definition: Dwarf.h:442
uint64_t
llvm::dwarf::DW_EH_PE_pcrel
@ DW_EH_PE_pcrel
Definition: Dwarf.h:448
Addr
uint64_t Addr
Definition: ELFObjHandler.cpp:78
move
compiles ldr LCPI1_0 ldr ldr mov lsr tst moveq r1 ldr LCPI1_1 and r0 bx lr It would be better to do something like to fold the shift into the conditional move
Definition: README.txt:546
assert
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
llvm::orc::ExecutorAddrRange::Start
ExecutorAddr Start
Definition: ExecutorAddress.h:171
llvm::dwarf::DW_EH_PE_datarel
@ DW_EH_PE_datarel
Definition: Dwarf.h:450
llvm::dwarf::DW_EH_PE_uleb128
@ DW_EH_PE_uleb128
Definition: Dwarf.h:439
llvm::StringRef
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:58
Dwarf.h
llvm_unreachable
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
Definition: ErrorHandling.h:143
uint32_t
S
add sub stmia L5 ldr r0 bl L_printf $stub Instead of a and a wouldn t it be better to do three moves *Return an aggregate type is even return S
Definition: README.txt:210
llvm::dwarf::DW_EH_PE_sleb128
@ DW_EH_PE_sleb128
Definition: Dwarf.h:443
llvm::dwarf::DW_EH_PE_absptr
@ DW_EH_PE_absptr
Definition: Dwarf.h:437
llvm::Error
Lightweight error class with error context and mandatory checking.
Definition: Error.h:155
llvm::Triple::MachO
@ MachO
Definition: Triple.h:276
llvm::sort
void sort(IteratorTy Start, IteratorTy End)
Definition: STLExtras.h:1552
EHFrameSupportImpl.h
DWARFRecordSectionSplitter.h
Version
uint64_t Version
Definition: RawMemProfReader.cpp:40
llvm::orc::registerEHFrameSection
Error registerEHFrameSection(const void *EHFrameSectionAddr, size_t EHFrameSectionSize)
Register frames in the given eh-frame section with libunwind.
Definition: RegisterEHFrames.cpp:128
llvm::dwarf::DW_EH_PE_omit
@ DW_EH_PE_omit
Definition: Dwarf.h:438
llvm::dwarf::DW_EH_PE_sdata2
@ DW_EH_PE_sdata2
Definition: Dwarf.h:444
llvm::dwarf::DW_EH_PE_aligned
@ DW_EH_PE_aligned
Definition: Dwarf.h:452
llvm::OptimizedStructLayoutField
A field in a structure.
Definition: OptimizedStructLayout.h:45