LLVM  14.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"
15 
16 #define DEBUG_TYPE "jitlink"
17 
18 namespace llvm {
19 namespace jitlink {
20 
22  : EHFrameSectionName(EHFrameSectionName) {}
23 
25  auto *EHFrame = G.findSectionByName(EHFrameSectionName);
26 
27  if (!EHFrame) {
28  LLVM_DEBUG({
29  dbgs() << "EHFrameSplitter: No " << EHFrameSectionName
30  << " section. Nothing to do\n";
31  });
32  return Error::success();
33  }
34 
35  LLVM_DEBUG({
36  dbgs() << "EHFrameSplitter: Processing " << EHFrameSectionName << "...\n";
37  });
38 
40 
41  {
42  // Pre-build the split caches.
43  for (auto *B : EHFrame->blocks())
45  for (auto *Sym : EHFrame->symbols())
46  Caches[&Sym->getBlock()]->push_back(Sym);
47  for (auto *B : EHFrame->blocks())
48  llvm::sort(*Caches[B], [](const Symbol *LHS, const Symbol *RHS) {
49  return LHS->getOffset() > RHS->getOffset();
50  });
51  }
52 
53  // Iterate over blocks (we do this by iterating over Caches entries rather
54  // than EHFrame->blocks() as we will be inserting new blocks along the way,
55  // which would invalidate iterators in the latter sequence.
56  for (auto &KV : Caches) {
57  auto &B = *KV.first;
58  auto &BCache = KV.second;
59  if (auto Err = processBlock(G, B, BCache))
60  return Err;
61  }
62 
63  return Error::success();
64 }
65 
66 Error EHFrameSplitter::processBlock(LinkGraph &G, Block &B,
68  LLVM_DEBUG({
69  dbgs() << " Processing block at " << formatv("{0:x16}", B.getAddress())
70  << "\n";
71  });
72 
73  // eh-frame should not contain zero-fill blocks.
74  if (B.isZeroFill())
75  return make_error<JITLinkError>("Unexpected zero-fill block in " +
76  EHFrameSectionName + " section");
77 
78  if (B.getSize() == 0) {
79  LLVM_DEBUG(dbgs() << " Block is empty. Skipping.\n");
80  return Error::success();
81  }
82 
83  BinaryStreamReader BlockReader(
84  StringRef(B.getContent().data(), B.getContent().size()),
85  G.getEndianness());
86 
87  while (true) {
88  uint64_t RecordStartOffset = BlockReader.getOffset();
89 
90  LLVM_DEBUG({
91  dbgs() << " Processing CFI record at "
92  << formatv("{0:x16}", B.getAddress()) << "\n";
93  });
94 
95  uint32_t Length;
96  if (auto Err = BlockReader.readInteger(Length))
97  return Err;
98  if (Length != 0xffffffff) {
99  if (auto Err = BlockReader.skip(Length))
100  return Err;
101  } else {
102  uint64_t ExtendedLength;
103  if (auto Err = BlockReader.readInteger(ExtendedLength))
104  return Err;
105  if (auto Err = BlockReader.skip(ExtendedLength))
106  return Err;
107  }
108 
109  // If this was the last block then there's nothing to split
110  if (BlockReader.empty()) {
111  LLVM_DEBUG(dbgs() << " Extracted " << B << "\n");
112  return Error::success();
113  }
114 
115  uint64_t BlockSize = BlockReader.getOffset() - RecordStartOffset;
116  auto &NewBlock = G.splitBlock(B, BlockSize);
117  (void)NewBlock;
118  LLVM_DEBUG(dbgs() << " Extracted " << NewBlock << "\n");
119  }
120 }
121 
123  unsigned PointerSize, Edge::Kind Delta64,
125  : EHFrameSectionName(EHFrameSectionName), PointerSize(PointerSize),
127 
129  auto *EHFrame = G.findSectionByName(EHFrameSectionName);
130 
131  if (!EHFrame) {
132  LLVM_DEBUG({
133  dbgs() << "EHFrameEdgeFixer: No " << EHFrameSectionName
134  << " section. Nothing to do\n";
135  });
136  return Error::success();
137  }
138 
139  // Check that we support the graph's pointer size.
140  if (G.getPointerSize() != 4 && G.getPointerSize() != 8)
141  return make_error<JITLinkError>(
142  "EHFrameEdgeFixer only supports 32 and 64 bit targets");
143 
144  LLVM_DEBUG({
145  dbgs() << "EHFrameEdgeFixer: Processing " << EHFrameSectionName << "...\n";
146  });
147 
148  ParseContext PC(G);
149 
150  // Build a map of all blocks and symbols in the text sections. We will use
151  // these for finding / building edge targets when processing FDEs.
152  for (auto &Sec : G.sections()) {
153  PC.AddrToSyms.addSymbols(Sec.symbols());
154  if (auto Err = PC.AddrToBlock.addBlocks(Sec.blocks(),
156  return Err;
157  }
158 
159  // Sort eh-frame blocks into address order to ensure we visit CIEs before
160  // their child FDEs.
161  std::vector<Block *> EHFrameBlocks;
162  for (auto *B : EHFrame->blocks())
163  EHFrameBlocks.push_back(B);
164  llvm::sort(EHFrameBlocks, [](const Block *LHS, const Block *RHS) {
165  return LHS->getAddress() < RHS->getAddress();
166  });
167 
168  // Loop over the blocks in address order.
169  for (auto *B : EHFrameBlocks)
170  if (auto Err = processBlock(PC, *B))
171  return Err;
172 
173  return Error::success();
174 }
175 
176 Error EHFrameEdgeFixer::processBlock(ParseContext &PC, Block &B) {
177 
178  LLVM_DEBUG({
179  dbgs() << " Processing block at " << formatv("{0:x16}", B.getAddress())
180  << "\n";
181  });
182 
183  // eh-frame should not contain zero-fill blocks.
184  if (B.isZeroFill())
185  return make_error<JITLinkError>("Unexpected zero-fill block in " +
186  EHFrameSectionName + " section");
187 
188  if (B.getSize() == 0) {
189  LLVM_DEBUG(dbgs() << " Block is empty. Skipping.\n");
190  return Error::success();
191  }
192 
193  // Find the offsets of any existing edges from this block.
194  BlockEdgeMap BlockEdges;
195  for (auto &E : B.edges())
196  if (E.isRelocation()) {
197  if (BlockEdges.count(E.getOffset()))
198  return make_error<JITLinkError>(
199  "Multiple relocations at offset " +
200  formatv("{0:x16}", E.getOffset()) + " in " + EHFrameSectionName +
201  " block at address " + formatv("{0:x16}", B.getAddress()));
202 
203  BlockEdges[E.getOffset()] = EdgeTarget(E);
204  }
205 
206  CIEInfosMap CIEInfos;
207  BinaryStreamReader BlockReader(
208  StringRef(B.getContent().data(), B.getContent().size()),
209  PC.G.getEndianness());
210  while (!BlockReader.empty()) {
211  size_t RecordStartOffset = BlockReader.getOffset();
212 
213  LLVM_DEBUG({
214  dbgs() << " Processing CFI record at "
215  << formatv("{0:x16}", B.getAddress() + RecordStartOffset) << "\n";
216  });
217 
218  // Get the record length.
219  size_t RecordRemaining;
220  {
221  uint32_t Length;
222  if (auto Err = BlockReader.readInteger(Length))
223  return Err;
224  // If Length < 0xffffffff then use the regular length field, otherwise
225  // read the extended length field.
226  if (Length != 0xffffffff)
227  RecordRemaining = Length;
228  else {
229  uint64_t ExtendedLength;
230  if (auto Err = BlockReader.readInteger(ExtendedLength))
231  return Err;
232  RecordRemaining = ExtendedLength;
233  }
234  }
235 
236  if (BlockReader.bytesRemaining() < RecordRemaining)
237  return make_error<JITLinkError>(
238  "Incomplete CFI record at " +
239  formatv("{0:x16}", B.getAddress() + RecordStartOffset));
240 
241  // Read the CIE delta for this record.
242  uint64_t CIEDeltaFieldOffset = BlockReader.getOffset() - RecordStartOffset;
243  uint32_t CIEDelta;
244  if (auto Err = BlockReader.readInteger(CIEDelta))
245  return Err;
246 
247  if (CIEDelta == 0) {
248  if (auto Err = processCIE(PC, B, RecordStartOffset,
249  CIEDeltaFieldOffset + RecordRemaining,
250  CIEDeltaFieldOffset))
251  return Err;
252  } else {
253  if (auto Err = processFDE(PC, B, RecordStartOffset,
254  CIEDeltaFieldOffset + RecordRemaining,
255  CIEDeltaFieldOffset, CIEDelta, BlockEdges))
256  return Err;
257  }
258 
259  // Move to the next record.
260  BlockReader.setOffset(RecordStartOffset + CIEDeltaFieldOffset +
261  RecordRemaining);
262  }
263 
264  return Error::success();
265 }
266 
267 Error EHFrameEdgeFixer::processCIE(ParseContext &PC, Block &B,
268  size_t RecordOffset, size_t RecordLength,
269  size_t CIEDeltaFieldOffset) {
270 
271  LLVM_DEBUG(dbgs() << " Record is CIE\n");
272 
273  auto RecordContent = B.getContent().slice(RecordOffset, RecordLength);
274  BinaryStreamReader RecordReader(
275  StringRef(RecordContent.data(), RecordContent.size()),
276  PC.G.getEndianness());
277 
278  // Skip past the CIE delta field: we've already processed this far.
279  RecordReader.setOffset(CIEDeltaFieldOffset + 4);
280 
281  auto &CIESymbol =
282  PC.G.addAnonymousSymbol(B, RecordOffset, RecordLength, false, false);
283  CIEInformation CIEInfo(CIESymbol);
284 
285  uint8_t Version = 0;
286  if (auto Err = RecordReader.readInteger(Version))
287  return Err;
288 
289  if (Version != 0x01)
290  return make_error<JITLinkError>("Bad CIE version " + Twine(Version) +
291  " (should be 0x01) in eh-frame");
292 
293  auto AugInfo = parseAugmentationString(RecordReader);
294  if (!AugInfo)
295  return AugInfo.takeError();
296 
297  // Skip the EH Data field if present.
298  if (AugInfo->EHDataFieldPresent)
299  if (auto Err = RecordReader.skip(PC.G.getPointerSize()))
300  return Err;
301 
302  // Read and sanity check the code alignment factor.
303  {
304  uint64_t CodeAlignmentFactor = 0;
305  if (auto Err = RecordReader.readULEB128(CodeAlignmentFactor))
306  return Err;
307  if (CodeAlignmentFactor != 1)
308  return make_error<JITLinkError>("Unsupported CIE code alignment factor " +
309  Twine(CodeAlignmentFactor) +
310  " (expected 1)");
311  }
312 
313  // Read and sanity check the data alignment factor.
314  {
315  int64_t DataAlignmentFactor = 0;
316  if (auto Err = RecordReader.readSLEB128(DataAlignmentFactor))
317  return Err;
318  if (DataAlignmentFactor != -8)
319  return make_error<JITLinkError>("Unsupported CIE data alignment factor " +
320  Twine(DataAlignmentFactor) +
321  " (expected -8)");
322  }
323 
324  // Skip the return address register field.
325  if (auto Err = RecordReader.skip(1))
326  return Err;
327 
328  uint64_t AugmentationDataLength = 0;
329  if (auto Err = RecordReader.readULEB128(AugmentationDataLength))
330  return Err;
331 
332  uint32_t AugmentationDataStartOffset = RecordReader.getOffset();
333 
334  uint8_t *NextField = &AugInfo->Fields[0];
335  while (uint8_t Field = *NextField++) {
336  switch (Field) {
337  case 'L': {
338  CIEInfo.FDEsHaveLSDAField = true;
339  uint8_t LSDAPointerEncoding;
340  if (auto Err = RecordReader.readInteger(LSDAPointerEncoding))
341  return Err;
342  if (!isSupportedPointerEncoding(LSDAPointerEncoding))
343  return make_error<JITLinkError>(
344  "Unsupported LSDA pointer encoding " +
345  formatv("{0:x2}", LSDAPointerEncoding) + " in CIE at " +
346  formatv("{0:x16}", CIESymbol.getAddress()));
347  CIEInfo.LSDAPointerEncoding = LSDAPointerEncoding;
348  break;
349  }
350  case 'P': {
351  uint8_t PersonalityPointerEncoding = 0;
352  if (auto Err = RecordReader.readInteger(PersonalityPointerEncoding))
353  return Err;
354  if (PersonalityPointerEncoding !=
357  return make_error<JITLinkError>(
358  "Unspported personality pointer "
359  "encoding " +
360  formatv("{0:x2}", PersonalityPointerEncoding) + " in CIE at " +
361  formatv("{0:x16}", CIESymbol.getAddress()));
362  uint32_t PersonalityPointerAddress;
363  if (auto Err = RecordReader.readInteger(PersonalityPointerAddress))
364  return Err;
365  break;
366  }
367  case 'R': {
368  uint8_t FDEPointerEncoding;
369  if (auto Err = RecordReader.readInteger(FDEPointerEncoding))
370  return Err;
371  if (!isSupportedPointerEncoding(FDEPointerEncoding))
372  return make_error<JITLinkError>(
373  "Unsupported FDE pointer encoding " +
374  formatv("{0:x2}", FDEPointerEncoding) + " in CIE at " +
375  formatv("{0:x16}", CIESymbol.getAddress()));
376  CIEInfo.FDEPointerEncoding = FDEPointerEncoding;
377  break;
378  }
379  default:
380  llvm_unreachable("Invalid augmentation string field");
381  }
382  }
383 
384  if (RecordReader.getOffset() - AugmentationDataStartOffset >
385  AugmentationDataLength)
386  return make_error<JITLinkError>("Read past the end of the augmentation "
387  "data while parsing fields");
388 
389  assert(!PC.CIEInfos.count(CIESymbol.getAddress()) &&
390  "Multiple CIEs recorded at the same address?");
391  PC.CIEInfos[CIESymbol.getAddress()] = std::move(CIEInfo);
392 
393  return Error::success();
394 }
395 
396 Error EHFrameEdgeFixer::processFDE(ParseContext &PC, Block &B,
397  size_t RecordOffset, size_t RecordLength,
398  size_t CIEDeltaFieldOffset,
399  uint32_t CIEDelta,
400  BlockEdgeMap &BlockEdges) {
401  LLVM_DEBUG(dbgs() << " Record is FDE\n");
402 
403  JITTargetAddress RecordAddress = B.getAddress() + RecordOffset;
404 
405  auto RecordContent = B.getContent().slice(RecordOffset, RecordLength);
406  BinaryStreamReader RecordReader(
407  StringRef(RecordContent.data(), RecordContent.size()),
408  PC.G.getEndianness());
409 
410  // Skip past the CIE delta field: we've already read this far.
411  RecordReader.setOffset(CIEDeltaFieldOffset + 4);
412 
413  auto &FDESymbol =
414  PC.G.addAnonymousSymbol(B, RecordOffset, RecordLength, false, false);
415 
416  CIEInformation *CIEInfo = nullptr;
417 
418  {
419  // Process the CIE pointer field.
420  auto CIEEdgeItr = BlockEdges.find(RecordOffset + CIEDeltaFieldOffset);
421  JITTargetAddress CIEAddress =
422  RecordAddress + CIEDeltaFieldOffset - CIEDelta;
423  if (CIEEdgeItr == BlockEdges.end()) {
424 
425  LLVM_DEBUG({
426  dbgs() << " Adding edge at "
427  << formatv("{0:x16}", RecordAddress + CIEDeltaFieldOffset)
428  << " to CIE at: " << formatv("{0:x16}", CIEAddress) << "\n";
429  });
430  if (auto CIEInfoOrErr = PC.findCIEInfo(CIEAddress))
431  CIEInfo = *CIEInfoOrErr;
432  else
433  return CIEInfoOrErr.takeError();
434  assert(CIEInfo->CIESymbol && "CIEInfo has no CIE symbol set");
435  B.addEdge(NegDelta32, RecordOffset + CIEDeltaFieldOffset,
436  *CIEInfo->CIESymbol, 0);
437  } else {
438  LLVM_DEBUG({
439  dbgs() << " Already has edge at "
440  << formatv("{0:x16}", RecordAddress + CIEDeltaFieldOffset)
441  << " to CIE at " << formatv("{0:x16}", CIEAddress) << "\n";
442  });
443  auto &EI = CIEEdgeItr->second;
444  if (EI.Addend)
445  return make_error<JITLinkError>(
446  "CIE edge at " +
447  formatv("{0:x16}", RecordAddress + CIEDeltaFieldOffset) +
448  " has non-zero addend");
449  if (auto CIEInfoOrErr = PC.findCIEInfo(EI.Target->getAddress()))
450  CIEInfo = *CIEInfoOrErr;
451  else
452  return CIEInfoOrErr.takeError();
453  }
454  }
455 
456  {
457  // Process the PC-Begin field.
458  Block *PCBeginBlock = nullptr;
459  JITTargetAddress PCBeginFieldOffset = RecordReader.getOffset();
460  auto PCEdgeItr = BlockEdges.find(RecordOffset + PCBeginFieldOffset);
461  if (PCEdgeItr == BlockEdges.end()) {
462  auto PCBeginPtrInfo =
463  readEncodedPointer(CIEInfo->FDEPointerEncoding,
464  RecordAddress + PCBeginFieldOffset, RecordReader);
465  if (!PCBeginPtrInfo)
466  return PCBeginPtrInfo.takeError();
467  JITTargetAddress PCBegin = PCBeginPtrInfo->first;
468  Edge::Kind PCBeginEdgeKind = PCBeginPtrInfo->second;
469  LLVM_DEBUG({
470  dbgs() << " Adding edge at "
471  << formatv("{0:x16}", RecordAddress + PCBeginFieldOffset)
472  << " to PC at " << formatv("{0:x16}", PCBegin) << "\n";
473  });
474  auto PCBeginSym = getOrCreateSymbol(PC, PCBegin);
475  if (!PCBeginSym)
476  return PCBeginSym.takeError();
477  B.addEdge(PCBeginEdgeKind, RecordOffset + PCBeginFieldOffset, *PCBeginSym,
478  0);
479  PCBeginBlock = &PCBeginSym->getBlock();
480  } else {
481  auto &EI = PCEdgeItr->second;
482  LLVM_DEBUG({
483  dbgs() << " Already has edge at "
484  << formatv("{0:x16}", RecordAddress + PCBeginFieldOffset)
485  << " to PC at " << formatv("{0:x16}", EI.Target->getAddress());
486  if (EI.Addend)
487  dbgs() << " + " << formatv("{0:x16}", EI.Addend);
488  dbgs() << "\n";
489  });
490 
491  // Make sure the existing edge points at a defined block.
492  if (!EI.Target->isDefined()) {
493  auto EdgeAddr = RecordAddress + PCBeginFieldOffset;
494  return make_error<JITLinkError>("FDE edge at " +
495  formatv("{0:x16}", EdgeAddr) +
496  " points at external block");
497  }
498  PCBeginBlock = &EI.Target->getBlock();
499  if (auto Err = RecordReader.skip(
500  getPointerEncodingDataSize(CIEInfo->FDEPointerEncoding)))
501  return Err;
502  }
503 
504  // Add a keep-alive edge from the FDE target to the FDE to ensure that the
505  // FDE is kept alive if its target is.
506  assert(PCBeginBlock && "PC-begin block not recorded");
507  LLVM_DEBUG({
508  dbgs() << " Adding keep-alive edge from target at "
509  << formatv("{0:x16}", PCBeginBlock->getAddress()) << " to FDE at "
510  << formatv("{0:x16}", RecordAddress) << "\n";
511  });
512  PCBeginBlock->addEdge(Edge::KeepAlive, 0, FDESymbol, 0);
513  }
514 
515  // Skip over the PC range size field.
516  if (auto Err = RecordReader.skip(
517  getPointerEncodingDataSize(CIEInfo->FDEPointerEncoding)))
518  return Err;
519 
520  if (CIEInfo->FDEsHaveLSDAField) {
521  uint64_t AugmentationDataSize;
522  if (auto Err = RecordReader.readULEB128(AugmentationDataSize))
523  return Err;
524 
525  JITTargetAddress LSDAFieldOffset = RecordReader.getOffset();
526  auto LSDAEdgeItr = BlockEdges.find(RecordOffset + LSDAFieldOffset);
527  if (LSDAEdgeItr == BlockEdges.end()) {
528  auto LSDAPointerInfo =
529  readEncodedPointer(CIEInfo->LSDAPointerEncoding,
530  RecordAddress + LSDAFieldOffset, RecordReader);
531  if (!LSDAPointerInfo)
532  return LSDAPointerInfo.takeError();
533  JITTargetAddress LSDA = LSDAPointerInfo->first;
534  Edge::Kind LSDAEdgeKind = LSDAPointerInfo->second;
535  auto LSDASym = getOrCreateSymbol(PC, LSDA);
536  if (!LSDASym)
537  return LSDASym.takeError();
538  LLVM_DEBUG({
539  dbgs() << " Adding edge at "
540  << formatv("{0:x16}", RecordAddress + LSDAFieldOffset)
541  << " to LSDA at " << formatv("{0:x16}", LSDA) << "\n";
542  });
543  B.addEdge(LSDAEdgeKind, RecordOffset + LSDAFieldOffset, *LSDASym, 0);
544  } else {
545  LLVM_DEBUG({
546  auto &EI = LSDAEdgeItr->second;
547  dbgs() << " Already has edge at "
548  << formatv("{0:x16}", RecordAddress + LSDAFieldOffset)
549  << " to LSDA at " << formatv("{0:x16}", EI.Target->getAddress());
550  if (EI.Addend)
551  dbgs() << " + " << formatv("{0:x16}", EI.Addend);
552  dbgs() << "\n";
553  });
554  if (auto Err = RecordReader.skip(AugmentationDataSize))
555  return Err;
556  }
557  } else {
558  LLVM_DEBUG(dbgs() << " Record does not have LSDA field.\n");
559  }
560 
561  return Error::success();
562 }
563 
564 Expected<EHFrameEdgeFixer::AugmentationInfo>
565 EHFrameEdgeFixer::parseAugmentationString(BinaryStreamReader &RecordReader) {
566  AugmentationInfo AugInfo;
567  uint8_t NextChar;
568  uint8_t *NextField = &AugInfo.Fields[0];
569 
570  if (auto Err = RecordReader.readInteger(NextChar))
571  return std::move(Err);
572 
573  while (NextChar != 0) {
574  switch (NextChar) {
575  case 'z':
576  AugInfo.AugmentationDataPresent = true;
577  break;
578  case 'e':
579  if (auto Err = RecordReader.readInteger(NextChar))
580  return std::move(Err);
581  if (NextChar != 'h')
582  return make_error<JITLinkError>("Unrecognized substring e" +
583  Twine(NextChar) +
584  " in augmentation string");
585  AugInfo.EHDataFieldPresent = true;
586  break;
587  case 'L':
588  case 'P':
589  case 'R':
590  *NextField++ = NextChar;
591  break;
592  default:
593  return make_error<JITLinkError>("Unrecognized character " +
594  Twine(NextChar) +
595  " in augmentation string");
596  }
597 
598  if (auto Err = RecordReader.readInteger(NextChar))
599  return std::move(Err);
600  }
601 
602  return std::move(AugInfo);
603 }
604 
605 bool EHFrameEdgeFixer::isSupportedPointerEncoding(uint8_t PointerEncoding) {
606  using namespace dwarf;
607 
608  // We only support PC-rel for now.
609  if ((PointerEncoding & 0x70) != DW_EH_PE_pcrel)
610  return false;
611 
612  // readEncodedPointer does not handle indirect.
613  if (PointerEncoding & DW_EH_PE_indirect)
614  return false;
615 
616  // Supported datatypes.
617  switch (PointerEncoding & 0xf) {
618  case DW_EH_PE_absptr:
619  case DW_EH_PE_udata4:
620  case DW_EH_PE_udata8:
621  case DW_EH_PE_sdata4:
622  case DW_EH_PE_sdata8:
623  return true;
624  }
625 
626  return false;
627 }
628 
629 unsigned EHFrameEdgeFixer::getPointerEncodingDataSize(uint8_t PointerEncoding) {
630  using namespace dwarf;
631 
632  assert(isSupportedPointerEncoding(PointerEncoding) &&
633  "Unsupported pointer encoding");
634  switch (PointerEncoding & 0xf) {
635  case DW_EH_PE_absptr:
636  return PointerSize;
637  case DW_EH_PE_udata4:
638  case DW_EH_PE_sdata4:
639  return 4;
640  case DW_EH_PE_udata8:
641  case DW_EH_PE_sdata8:
642  return 8;
643  default:
644  llvm_unreachable("Unsupported encoding");
645  }
646 }
647 
648 Expected<std::pair<JITTargetAddress, Edge::Kind>>
649 EHFrameEdgeFixer::readEncodedPointer(uint8_t PointerEncoding,
650  JITTargetAddress PointerFieldAddress,
651  BinaryStreamReader &RecordReader) {
652  static_assert(sizeof(JITTargetAddress) == sizeof(uint64_t),
653  "Result must be able to hold a uint64_t");
654  assert(isSupportedPointerEncoding(PointerEncoding) &&
655  "Unsupported pointer encoding");
656 
657  using namespace dwarf;
658 
659  // Isolate data type, remap absptr to udata4 or udata8. This relies on us
660  // having verified that the graph uses 32-bit or 64-bit pointers only at the
661  // start of this pass.
662  uint8_t EffectiveType = PointerEncoding & 0xf;
663  if (EffectiveType == DW_EH_PE_absptr)
664  EffectiveType = (PointerSize == 8) ? DW_EH_PE_udata8 : DW_EH_PE_udata4;
665 
667  Edge::Kind PointerEdgeKind = Edge::Invalid;
668  switch (EffectiveType) {
669  case DW_EH_PE_udata4: {
670  uint32_t Val;
671  if (auto Err = RecordReader.readInteger(Val))
672  return std::move(Err);
673  Addr = PointerFieldAddress + Val;
674  PointerEdgeKind = Delta32;
675  break;
676  }
677  case DW_EH_PE_udata8: {
678  uint64_t Val;
679  if (auto Err = RecordReader.readInteger(Val))
680  return std::move(Err);
681  Addr = PointerFieldAddress + Val;
682  PointerEdgeKind = Delta64;
683  break;
684  }
685  case DW_EH_PE_sdata4: {
686  int32_t Val;
687  if (auto Err = RecordReader.readInteger(Val))
688  return std::move(Err);
689  Addr = PointerFieldAddress + Val;
690  PointerEdgeKind = Delta32;
691  break;
692  }
693  case DW_EH_PE_sdata8: {
694  int64_t Val;
695  if (auto Err = RecordReader.readInteger(Val))
696  return std::move(Err);
697  Addr = PointerFieldAddress + Val;
698  PointerEdgeKind = Delta64;
699  break;
700  }
701  }
702 
703  if (PointerEdgeKind == Edge::Invalid)
704  return make_error<JITLinkError>(
705  "Unspported edge kind for encoded pointer at " +
706  formatv("{0:x}", PointerFieldAddress));
707 
708  return std::make_pair(Addr, Delta64);
709 }
710 
711 Expected<Symbol &> EHFrameEdgeFixer::getOrCreateSymbol(ParseContext &PC,
713  Symbol *CanonicalSym = nullptr;
714 
715  auto UpdateCanonicalSym = [&](Symbol *Sym) {
716  if (!CanonicalSym || Sym->getLinkage() < CanonicalSym->getLinkage() ||
717  Sym->getScope() < CanonicalSym->getScope() ||
718  (Sym->hasName() && !CanonicalSym->hasName()) ||
719  Sym->getName() < CanonicalSym->getName())
720  CanonicalSym = Sym;
721  };
722 
723  if (auto *SymbolsAtAddr = PC.AddrToSyms.getSymbolsAt(Addr))
724  for (auto *Sym : *SymbolsAtAddr)
725  UpdateCanonicalSym(Sym);
726 
727  // If we found an existing symbol at the given address then use it.
728  if (CanonicalSym)
729  return *CanonicalSym;
730 
731  // Otherwise search for a block covering the address and create a new symbol.
732  auto *B = PC.AddrToBlock.getBlockCovering(Addr);
733  if (!B)
734  return make_error<JITLinkError>("No symbol or block covering address " +
735  formatv("{0:x16}", Addr));
736 
737  return PC.G.addAnonymousSymbol(*B, Addr - B->getAddress(), 0, false, false);
738 }
739 
740 char EHFrameNullTerminator::NullTerminatorBlockContent[4] = {0, 0, 0, 0};
741 
743  : EHFrameSectionName(EHFrameSectionName) {}
744 
746  auto *EHFrame = G.findSectionByName(EHFrameSectionName);
747 
748  if (!EHFrame)
749  return Error::success();
750 
751  LLVM_DEBUG({
752  dbgs() << "EHFrameNullTerminator adding null terminator to "
753  << EHFrameSectionName << "\n";
754  });
755 
756  auto &NullTerminatorBlock = G.createContentBlock(
757  *EHFrame, NullTerminatorBlockContent, 0xfffffffffffffffc, 1, 0);
758  G.addAnonymousSymbol(NullTerminatorBlock, 0, 4, false, true);
759  return Error::success();
760 }
761 
763 
765  JITTargetAddress EHFrameSectionAddr, size_t EHFrameSectionSize) {
767  jitTargetAddressToPointer<void *>(EHFrameSectionAddr),
768  EHFrameSectionSize);
769 }
770 
772  JITTargetAddress EHFrameSectionAddr, size_t EHFrameSectionSize) {
774  jitTargetAddressToPointer<void *>(EHFrameSectionAddr),
775  EHFrameSectionSize);
776 }
777 
780  StoreFrameRangeFunction StoreRangeAddress) {
781  const char *EHFrameSectionName = nullptr;
782  if (TT.getObjectFormat() == Triple::MachO)
783  EHFrameSectionName = "__TEXT,__eh_frame";
784  else
785  EHFrameSectionName = ".eh_frame";
786 
787  auto RecordEHFrame =
788  [EHFrameSectionName,
789  StoreFrameRange = std::move(StoreRangeAddress)](LinkGraph &G) -> Error {
790  // Search for a non-empty eh-frame and record the address of the first
791  // symbol in it.
793  size_t Size = 0;
794  if (auto *S = G.findSectionByName(EHFrameSectionName)) {
795  auto R = SectionRange(*S);
796  Addr = R.getStart();
797  Size = R.getSize();
798  }
799  if (Addr == 0 && Size != 0)
800  return make_error<JITLinkError>(
801  StringRef(EHFrameSectionName) +
802  " section can not have zero address with non-zero size");
803  StoreFrameRange(Addr, Size);
804  return Error::success();
805  };
806 
807  return RecordEHFrame;
808 }
809 
810 } // end namespace jitlink
811 } // end namespace llvm
llvm::Check::Size
@ Size
Definition: FileCheck.h:73
llvm::Optional::value_type
T value_type
Definition: Optional.h:242
llvm
This file implements support for optimizing divisions by a constant.
Definition: AllocatorList.h:23
BlockSize
static const int BlockSize
Definition: TarWriter.cpp:33
llvm::dwarf::DW_EH_PE_sdata4
@ DW_EH_PE_sdata4
Definition: Dwarf.h:440
llvm::lltok::Error
@ Error
Definition: LLToken.h:21
llvm::Error::success
static ErrorSuccess success()
Create a success value.
Definition: Error.h:331
llvm::dwarf::DW_EH_PE_sdata8
@ DW_EH_PE_sdata8
Definition: Dwarf.h:441
llvm::Triple
Triple - Helper class for working with autoconf configuration names.
Definition: Triple.h:45
DynamicLibrary.h
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::Optional
Definition: APInt.h:33
LLVM_DEBUG
#define LLVM_DEBUG(X)
Definition: Debug.h:101
llvm::dbgs
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition: Debug.cpp:163
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:250
llvm::dwarf::DW_EH_PE_indirect
@ DW_EH_PE_indirect
Definition: Dwarf.h:448
E
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
B
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
RegisterEHFrames.h
llvm::IndexedInstrProf::Version
const uint64_t Version
Definition: InstrProf.h:991
llvm::dwarf::DW_EH_PE_udata4
@ DW_EH_PE_udata4
Definition: Dwarf.h:436
G
const DataFlowGraph & G
Definition: RDFGraph.cpp:202
llvm::dwarf::DW_EH_PE_udata8
@ DW_EH_PE_udata8
Definition: Dwarf.h:437
uint64_t
llvm::dwarf::DW_EH_PE_pcrel
@ DW_EH_PE_pcrel
Definition: Dwarf.h:443
Addr
uint64_t Addr
Definition: ELFObjHandler.cpp:80
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
llvm::DenseMap
Definition: DenseMap.h:714
assert
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
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:134
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_absptr
@ DW_EH_PE_absptr
Definition: Dwarf.h:432
llvm::Error
Lightweight error class with error context and mandatory checking.
Definition: Error.h:157
llvm::Triple::MachO
@ MachO
Definition: Triple.h:240
llvm::sort
void sort(IteratorTy Start, IteratorTy End)
Definition: STLExtras.h:1492
EHFrameSupportImpl.h
llvm::JITTargetAddress
uint64_t JITTargetAddress
Represents an address in the target process's address space.
Definition: JITSymbol.h:42
llvm::ARMBuildAttrs::Symbol
@ Symbol
Definition: ARMBuildAttributes.h:79
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::OptimizedStructLayoutField
A field in a structure.
Definition: OptimizedStructLayout.h:45
llvm::pdb::PDB_SymType::Block
@ Block