LLVM  13.0.0git
DWARFDebugFrame.cpp
Go to the documentation of this file.
1 //===- DWARFDebugFrame.h - Parsing of .debug_frame ------------------------===//
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 
10 #include "llvm/ADT/DenseMap.h"
11 #include "llvm/ADT/Optional.h"
12 #include "llvm/ADT/StringExtras.h"
13 #include "llvm/ADT/StringRef.h"
15 #include "llvm/MC/MCRegisterInfo.h"
16 #include "llvm/Support/Casting.h"
17 #include "llvm/Support/Compiler.h"
19 #include "llvm/Support/Errc.h"
21 #include "llvm/Support/Format.h"
23 #include <algorithm>
24 #include <cassert>
25 #include <cinttypes>
26 #include <cstdint>
27 #include <string>
28 
29 using namespace llvm;
30 using namespace dwarf;
31 
32 static void printRegister(raw_ostream &OS, const MCRegisterInfo *MRI, bool IsEH,
33  unsigned RegNum) {
34  if (MRI) {
35  if (Optional<unsigned> LLVMRegNum = MRI->getLLVMRegNum(RegNum, IsEH)) {
36  if (const char *RegName = MRI->getName(*LLVMRegNum)) {
37  OS << RegName;
38  return;
39  }
40  }
41  }
42  OS << "reg" << RegNum;
43 }
44 
46 
48 
50 
52  return {Constant, InvalidRegisterNumber, Value, false};
53 }
54 
56  return {CFAPlusOffset, InvalidRegisterNumber, Offset, false};
57 }
58 
60  return {CFAPlusOffset, InvalidRegisterNumber, Offset, true};
61 }
62 
64  int32_t Offset) {
65  return {RegPlusOffset, RegNum, Offset, false};
66 }
68  int32_t Offset) {
69  return {RegPlusOffset, RegNum, Offset, true};
70 }
71 
73  return {Expr, false};
74 }
75 
77  return {Expr, true};
78 }
79 
81  bool IsEH) const {
82  if (Dereference)
83  OS << '[';
84  switch (Kind) {
85  case Unspecified:
86  OS << "unspecified";
87  break;
88  case Undefined:
89  OS << "undefined";
90  break;
91  case Same:
92  OS << "same";
93  break;
94  case CFAPlusOffset:
95  OS << "CFA";
96  if (Offset == 0)
97  break;
98  if (Offset > 0)
99  OS << "+";
100  OS << Offset;
101  break;
102  case RegPlusOffset:
103  printRegister(OS, MRI, IsEH, RegNum);
104  if (Offset == 0)
105  break;
106  if (Offset > 0)
107  OS << "+";
108  OS << Offset;
109  break;
110  case DWARFExpr:
111  Expr->print(OS, DIDumpOptions(), MRI, nullptr, IsEH);
112  break;
113  case Constant:
114  OS << Offset;
115  break;
116  }
117  if (Dereference)
118  OS << ']';
119 }
120 
122  const UnwindLocation &UL) {
123  UL.dump(OS, nullptr, false);
124  return OS;
125 }
126 
128  if (Kind != RHS.Kind)
129  return false;
130  switch (Kind) {
131  case Unspecified:
132  case Undefined:
133  case Same:
134  return true;
135  case CFAPlusOffset:
136  return Offset == RHS.Offset && Dereference == RHS.Dereference;
137  case RegPlusOffset:
138  return RegNum == RHS.RegNum && Offset == RHS.Offset &&
139  Dereference == RHS.Dereference;
140  case DWARFExpr:
141  return *Expr == *RHS.Expr && Dereference == RHS.Dereference;
142  case Constant:
143  return Offset == RHS.Offset;
144  }
145  return false;
146 }
147 
149  bool IsEH) const {
150  bool First = true;
151  for (const auto &RegLocPair : Locations) {
152  if (First)
153  First = false;
154  else
155  OS << ", ";
156  printRegister(OS, MRI, IsEH, RegLocPair.first);
157  OS << '=';
158  RegLocPair.second.dump(OS, MRI, IsEH);
159  }
160 }
161 
163  const RegisterLocations &RL) {
164  RL.dump(OS, nullptr, false);
165  return OS;
166 }
167 
168 void UnwindRow::dump(raw_ostream &OS, const MCRegisterInfo *MRI, bool IsEH,
169  unsigned IndentLevel) const {
170  OS.indent(2 * IndentLevel);
171  if (hasAddress())
172  OS << format("0x%" PRIx64 ": ", *Address);
173  OS << "CFA=";
174  CFAValue.dump(OS, MRI, IsEH);
175  if (RegLocs.hasLocations()) {
176  OS << ": ";
177  RegLocs.dump(OS, MRI, IsEH);
178  }
179  OS << "\n";
180 }
181 
183  Row.dump(OS, nullptr, false, 0);
184  return OS;
185 }
186 
187 void UnwindTable::dump(raw_ostream &OS, const MCRegisterInfo *MRI, bool IsEH,
188  unsigned IndentLevel) const {
189  for (const UnwindRow &Row : Rows)
190  Row.dump(OS, MRI, IsEH, IndentLevel);
191 }
192 
194  Rows.dump(OS, nullptr, false, 0);
195  return OS;
196 }
197 
199  UnwindTable UT;
200  UnwindRow Row;
201  Row.setAddress(Fde->getInitialLocation());
202  UT.EndAddress = Fde->getInitialLocation() + Fde->getAddressRange();
203 
204  const CIE *Cie = Fde->getLinkedCIE();
205  if (Cie == nullptr)
207  "unable to get CIE for FDE at offset 0x%" PRIx64,
208  Fde->getOffset());
209 
210  if (Error CieError = UT.parseRows(Cie->cfis(), Row, nullptr))
211  return std::move(CieError);
212  // We need to save the initial locations of registers from the CIE parsing
213  // in case we run into DW_CFA_restore or DW_CFA_restore_extended opcodes.
214  const RegisterLocations InitialLocs = Row.getRegisterLocations();
215  if (Error FdeError = UT.parseRows(Fde->cfis(), Row, &InitialLocs))
216  return std::move(FdeError);
217  UT.Rows.push_back(Row);
218  return UT;
219 }
220 
222  UnwindTable UT;
223  UnwindRow Row;
224  if (Error CieError = UT.parseRows(Cie->cfis(), Row, nullptr))
225  return std::move(CieError);
226  UT.Rows.push_back(Row);
227  return UT;
228 }
229 
230 // See DWARF standard v3, section 7.23
231 const uint8_t DWARF_CFI_PRIMARY_OPCODE_MASK = 0xc0;
232 const uint8_t DWARF_CFI_PRIMARY_OPERAND_MASK = 0x3f;
233 
235  uint64_t EndOffset) {
237  while (C && C.tell() < EndOffset) {
238  uint8_t Opcode = Data.getRelocatedValue(C, 1);
239  if (!C)
240  break;
241 
242  // Some instructions have a primary opcode encoded in the top bits.
243  if (uint8_t Primary = Opcode & DWARF_CFI_PRIMARY_OPCODE_MASK) {
244  // If it's a primary opcode, the first operand is encoded in the bottom
245  // bits of the opcode itself.
246  uint64_t Op1 = Opcode & DWARF_CFI_PRIMARY_OPERAND_MASK;
247  switch (Primary) {
248  case DW_CFA_advance_loc:
249  case DW_CFA_restore:
250  addInstruction(Primary, Op1);
251  break;
252  case DW_CFA_offset:
253  addInstruction(Primary, Op1, Data.getULEB128(C));
254  break;
255  default:
256  llvm_unreachable("invalid primary CFI opcode");
257  }
258  continue;
259  }
260 
261  // Extended opcode - its value is Opcode itself.
262  switch (Opcode) {
263  default:
265  "invalid extended CFI opcode 0x%" PRIx8, Opcode);
266  case DW_CFA_nop:
267  case DW_CFA_remember_state:
268  case DW_CFA_restore_state:
269  case DW_CFA_GNU_window_save:
270  // No operands
271  addInstruction(Opcode);
272  break;
273  case DW_CFA_set_loc:
274  // Operands: Address
275  addInstruction(Opcode, Data.getRelocatedAddress(C));
276  break;
277  case DW_CFA_advance_loc1:
278  // Operands: 1-byte delta
279  addInstruction(Opcode, Data.getRelocatedValue(C, 1));
280  break;
281  case DW_CFA_advance_loc2:
282  // Operands: 2-byte delta
283  addInstruction(Opcode, Data.getRelocatedValue(C, 2));
284  break;
285  case DW_CFA_advance_loc4:
286  // Operands: 4-byte delta
287  addInstruction(Opcode, Data.getRelocatedValue(C, 4));
288  break;
289  case DW_CFA_restore_extended:
290  case DW_CFA_undefined:
291  case DW_CFA_same_value:
292  case DW_CFA_def_cfa_register:
293  case DW_CFA_def_cfa_offset:
294  case DW_CFA_GNU_args_size:
295  // Operands: ULEB128
296  addInstruction(Opcode, Data.getULEB128(C));
297  break;
298  case DW_CFA_def_cfa_offset_sf:
299  // Operands: SLEB128
300  addInstruction(Opcode, Data.getSLEB128(C));
301  break;
302  case DW_CFA_offset_extended:
303  case DW_CFA_register:
304  case DW_CFA_def_cfa:
305  case DW_CFA_val_offset: {
306  // Operands: ULEB128, ULEB128
307  // Note: We can not embed getULEB128 directly into function
308  // argument list. getULEB128 changes Offset and order of evaluation
309  // for arguments is unspecified.
310  uint64_t op1 = Data.getULEB128(C);
311  uint64_t op2 = Data.getULEB128(C);
312  addInstruction(Opcode, op1, op2);
313  break;
314  }
315  case DW_CFA_offset_extended_sf:
316  case DW_CFA_def_cfa_sf:
317  case DW_CFA_val_offset_sf: {
318  // Operands: ULEB128, SLEB128
319  // Note: see comment for the previous case
320  uint64_t op1 = Data.getULEB128(C);
321  uint64_t op2 = (uint64_t)Data.getSLEB128(C);
322  addInstruction(Opcode, op1, op2);
323  break;
324  }
325  case DW_CFA_def_cfa_expression: {
326  uint64_t ExprLength = Data.getULEB128(C);
327  addInstruction(Opcode, 0);
328  StringRef Expression = Data.getBytes(C, ExprLength);
329 
330  DataExtractor Extractor(Expression, Data.isLittleEndian(),
331  Data.getAddressSize());
332  // Note. We do not pass the DWARF format to DWARFExpression, because
333  // DW_OP_call_ref, the only operation which depends on the format, is
334  // prohibited in call frame instructions, see sec. 6.4.2 in DWARFv5.
335  Instructions.back().Expression =
336  DWARFExpression(Extractor, Data.getAddressSize());
337  break;
338  }
339  case DW_CFA_expression:
340  case DW_CFA_val_expression: {
341  uint64_t RegNum = Data.getULEB128(C);
342  addInstruction(Opcode, RegNum, 0);
343 
344  uint64_t BlockLength = Data.getULEB128(C);
345  StringRef Expression = Data.getBytes(C, BlockLength);
346  DataExtractor Extractor(Expression, Data.isLittleEndian(),
347  Data.getAddressSize());
348  // Note. We do not pass the DWARF format to DWARFExpression, because
349  // DW_OP_call_ref, the only operation which depends on the format, is
350  // prohibited in call frame instructions, see sec. 6.4.2 in DWARFv5.
351  Instructions.back().Expression =
352  DWARFExpression(Extractor, Data.getAddressSize());
353  break;
354  }
355  }
356  }
357 
358  *Offset = C.tell();
359  return C.takeError();
360 }
361 
362 StringRef CFIProgram::callFrameString(unsigned Opcode) const {
363  return dwarf::CallFrameString(Opcode, Arch);
364 }
365 
366 const char *CFIProgram::operandTypeString(CFIProgram::OperandType OT) {
367 #define ENUM_TO_CSTR(e) \
368  case e: \
369  return #e;
370  switch (OT) {
371  ENUM_TO_CSTR(OT_Unset);
372  ENUM_TO_CSTR(OT_None);
373  ENUM_TO_CSTR(OT_Address);
374  ENUM_TO_CSTR(OT_Offset);
375  ENUM_TO_CSTR(OT_FactoredCodeOffset);
376  ENUM_TO_CSTR(OT_SignedFactDataOffset);
377  ENUM_TO_CSTR(OT_UnsignedFactDataOffset);
378  ENUM_TO_CSTR(OT_Register);
379  ENUM_TO_CSTR(OT_Expression);
380  }
381  return "<unknown CFIProgram::OperandType>";
382 }
383 
386  uint32_t OperandIdx) const {
387  if (OperandIdx >= 2)
389  "operand index %" PRIu32 " is not valid",
390  OperandIdx);
391  OperandType Type = CFIP.getOperandTypes()[Opcode][OperandIdx];
392  uint64_t Operand = Ops[OperandIdx];
393  switch (Type) {
394  case OT_Unset:
395  case OT_None:
396  case OT_Expression:
398  "op[%" PRIu32 "] has type %s which has no value",
399  OperandIdx, CFIProgram::operandTypeString(Type));
400 
401  case OT_Offset:
402  case OT_SignedFactDataOffset:
403  case OT_UnsignedFactDataOffset:
404  return createStringError(
406  "op[%" PRIu32 "] has OperandType OT_Offset which produces a signed "
407  "result, call getOperandAsSigned instead",
408  OperandIdx);
409 
410  case OT_Address:
411  case OT_Register:
412  return Operand;
413 
414  case OT_FactoredCodeOffset: {
415  const uint64_t CodeAlignmentFactor = CFIP.codeAlign();
416  if (CodeAlignmentFactor == 0)
417  return createStringError(
419  "op[%" PRIu32 "] has type OT_FactoredCodeOffset but code alignment "
420  "is zero",
421  OperandIdx);
422  return Operand * CodeAlignmentFactor;
423  }
424  }
425  llvm_unreachable("invalid operand type");
426 }
427 
430  uint32_t OperandIdx) const {
431  if (OperandIdx >= 2)
433  "operand index %" PRIu32 " is not valid",
434  OperandIdx);
435  OperandType Type = CFIP.getOperandTypes()[Opcode][OperandIdx];
436  uint64_t Operand = Ops[OperandIdx];
437  switch (Type) {
438  case OT_Unset:
439  case OT_None:
440  case OT_Expression:
442  "op[%" PRIu32 "] has type %s which has no value",
443  OperandIdx, CFIProgram::operandTypeString(Type));
444 
445  case OT_Address:
446  case OT_Register:
447  return createStringError(
449  "op[%" PRIu32 "] has OperandType %s which produces an unsigned result, "
450  "call getOperandAsUnsigned instead",
451  OperandIdx, CFIProgram::operandTypeString(Type));
452 
453  case OT_Offset:
454  return (int64_t)Operand;
455 
456  case OT_FactoredCodeOffset:
457  case OT_SignedFactDataOffset: {
458  const int64_t DataAlignmentFactor = CFIP.dataAlign();
459  if (DataAlignmentFactor == 0)
461  "op[%" PRIu32 "] has type %s but data "
462  "alignment is zero",
463  OperandIdx, CFIProgram::operandTypeString(Type));
464  return int64_t(Operand) * DataAlignmentFactor;
465  }
466 
467  case OT_UnsignedFactDataOffset: {
468  const int64_t DataAlignmentFactor = CFIP.dataAlign();
469  if (DataAlignmentFactor == 0)
471  "op[%" PRIu32
472  "] has type OT_UnsignedFactDataOffset but data "
473  "alignment is zero",
474  OperandIdx);
475  return Operand * DataAlignmentFactor;
476  }
477  }
478  llvm_unreachable("invalid operand type");
479 }
480 
481 Error UnwindTable::parseRows(const CFIProgram &CFIP, UnwindRow &Row,
482  const RegisterLocations *InitialLocs) {
483  std::vector<RegisterLocations> RegisterStates;
484  for (const CFIProgram::Instruction &Inst : CFIP) {
485  switch (Inst.Opcode) {
486  case dwarf::DW_CFA_set_loc: {
487  // The DW_CFA_set_loc instruction takes a single operand that
488  // represents a target address. The required action is to create a new
489  // table row using the specified address as the location. All other
490  // values in the new row are initially identical to the current row.
491  // The new location value is always greater than the current one. If
492  // the segment_size field of this FDE's CIE is non- zero, the initial
493  // location is preceded by a segment selector of the given length
494  llvm::Expected<uint64_t> NewAddress = Inst.getOperandAsUnsigned(CFIP, 0);
495  if (!NewAddress)
496  return NewAddress.takeError();
497  if (*NewAddress <= Row.getAddress())
498  return createStringError(
500  "%s with adrress 0x%" PRIx64 " which must be greater than the "
501  "current row address 0x%" PRIx64,
502  CFIP.callFrameString(Inst.Opcode).str().c_str(), *NewAddress,
503  Row.getAddress());
504  Rows.push_back(Row);
505  Row.setAddress(*NewAddress);
506  break;
507  }
508 
509  case dwarf::DW_CFA_advance_loc:
510  case dwarf::DW_CFA_advance_loc1:
511  case dwarf::DW_CFA_advance_loc2:
512  case dwarf::DW_CFA_advance_loc4: {
513  // The DW_CFA_advance instruction takes a single operand that
514  // represents a constant delta. The required action is to create a new
515  // table row with a location value that is computed by taking the
516  // current entry‚Äôs location value and adding the value of delta *
517  // code_alignment_factor. All other values in the new row are initially
518  // identical to the current row.
519  Rows.push_back(Row);
520  llvm::Expected<uint64_t> Offset = Inst.getOperandAsUnsigned(CFIP, 0);
521  if (!Offset)
522  return Offset.takeError();
523  Row.slideAddress(*Offset);
524  break;
525  }
526 
527  case dwarf::DW_CFA_restore:
528  case dwarf::DW_CFA_restore_extended: {
529  // The DW_CFA_restore instruction takes a single operand (encoded with
530  // the opcode) that represents a register number. The required action
531  // is to change the rule for the indicated register to the rule
532  // assigned it by the initial_instructions in the CIE.
533  if (InitialLocs == nullptr)
534  return createStringError(
535  errc::invalid_argument, "%s encountered while parsing a CIE",
536  CFIP.callFrameString(Inst.Opcode).str().c_str());
537  llvm::Expected<uint64_t> RegNum = Inst.getOperandAsUnsigned(CFIP, 0);
538  if (!RegNum)
539  return RegNum.takeError();
541  InitialLocs->getRegisterLocation(*RegNum))
542  Row.getRegisterLocations().setRegisterLocation(*RegNum, *O);
543  else
545  break;
546  }
547 
548  case dwarf::DW_CFA_offset:
549  case dwarf::DW_CFA_offset_extended:
550  case dwarf::DW_CFA_offset_extended_sf: {
551  llvm::Expected<uint64_t> RegNum = Inst.getOperandAsUnsigned(CFIP, 0);
552  if (!RegNum)
553  return RegNum.takeError();
554  llvm::Expected<int64_t> Offset = Inst.getOperandAsSigned(CFIP, 1);
555  if (!Offset)
556  return Offset.takeError();
559  break;
560  }
561 
562  case dwarf::DW_CFA_nop:
563  break;
564 
565  case dwarf::DW_CFA_remember_state:
566  RegisterStates.push_back(Row.getRegisterLocations());
567  break;
568 
569  case dwarf::DW_CFA_restore_state:
570  if (RegisterStates.empty())
572  "DW_CFA_restore_state without a matching "
573  "previous DW_CFA_remember_state");
574  Row.getRegisterLocations() = RegisterStates.back();
575  RegisterStates.pop_back();
576  break;
577 
578  case dwarf::DW_CFA_GNU_window_save:
579  switch (CFIP.triple()) {
580  case Triple::aarch64:
581  case Triple::aarch64_be:
582  case Triple::aarch64_32: {
583  // DW_CFA_GNU_window_save is used for different things on different
584  // architectures. For aarch64 it is known as
585  // DW_CFA_AARCH64_negate_ra_state. The action is to toggle the
586  // value of the return address state between 1 and 0. If there is
587  // no rule for the AARCH64_DWARF_PAUTH_RA_STATE register, then it
588  // should be initially set to 1.
589  constexpr uint32_t AArch64DWARFPAuthRaState = 34;
590  auto LRLoc = Row.getRegisterLocations().getRegisterLocation(
591  AArch64DWARFPAuthRaState);
592  if (LRLoc) {
593  if (LRLoc->getLocation() == UnwindLocation::Constant) {
594  // Toggle the constant value from 0 to 1 or 1 to 0.
595  LRLoc->setConstant(LRLoc->getConstant() ^ 1);
596  } else {
597  return createStringError(
599  "%s encountered when existing rule for this register is not "
600  "a constant",
601  CFIP.callFrameString(Inst.Opcode).str().c_str());
602  }
603  } else {
605  AArch64DWARFPAuthRaState, UnwindLocation::createIsConstant(1));
606  }
607  break;
608  }
609 
610  case Triple::sparc:
611  case Triple::sparcv9:
612  case Triple::sparcel:
613  for (uint32_t RegNum = 16; RegNum < 32; ++RegNum) {
615  RegNum, UnwindLocation::createAtCFAPlusOffset((RegNum - 16) * 8));
616  }
617  break;
618 
619  default: {
620  return createStringError(
622  "DW_CFA opcode %#x is not supported for architecture %s",
623  Inst.Opcode, Triple::getArchTypeName(CFIP.triple()).str().c_str());
624 
625  break;
626  }
627  }
628  break;
629 
630  case dwarf::DW_CFA_undefined: {
631  llvm::Expected<uint64_t> RegNum = Inst.getOperandAsUnsigned(CFIP, 0);
632  if (!RegNum)
633  return RegNum.takeError();
636  break;
637  }
638 
639  case dwarf::DW_CFA_same_value: {
640  llvm::Expected<uint64_t> RegNum = Inst.getOperandAsUnsigned(CFIP, 0);
641  if (!RegNum)
642  return RegNum.takeError();
644  *RegNum, UnwindLocation::createSame());
645  break;
646  }
647 
648  case dwarf::DW_CFA_GNU_args_size:
649  break;
650 
651  case dwarf::DW_CFA_register: {
652  llvm::Expected<uint64_t> RegNum = Inst.getOperandAsUnsigned(CFIP, 0);
653  if (!RegNum)
654  return RegNum.takeError();
655  llvm::Expected<uint64_t> NewRegNum = Inst.getOperandAsUnsigned(CFIP, 1);
656  if (!NewRegNum)
657  return NewRegNum.takeError();
659  *RegNum, UnwindLocation::createIsRegisterPlusOffset(*NewRegNum, 0));
660  break;
661  }
662 
663  case dwarf::DW_CFA_val_offset:
664  case dwarf::DW_CFA_val_offset_sf: {
665  llvm::Expected<uint64_t> RegNum = Inst.getOperandAsUnsigned(CFIP, 0);
666  if (!RegNum)
667  return RegNum.takeError();
668  llvm::Expected<int64_t> Offset = Inst.getOperandAsSigned(CFIP, 1);
669  if (!Offset)
670  return Offset.takeError();
673  break;
674  }
675 
676  case dwarf::DW_CFA_expression: {
677  llvm::Expected<uint64_t> RegNum = Inst.getOperandAsUnsigned(CFIP, 0);
678  if (!RegNum)
679  return RegNum.takeError();
681  *RegNum, UnwindLocation::createAtDWARFExpression(*Inst.Expression));
682  break;
683  }
684 
685  case dwarf::DW_CFA_val_expression: {
686  llvm::Expected<uint64_t> RegNum = Inst.getOperandAsUnsigned(CFIP, 0);
687  if (!RegNum)
688  return RegNum.takeError();
690  *RegNum, UnwindLocation::createIsDWARFExpression(*Inst.Expression));
691  break;
692  }
693 
694  case dwarf::DW_CFA_def_cfa_register: {
695  llvm::Expected<uint64_t> RegNum = Inst.getOperandAsUnsigned(CFIP, 0);
696  if (!RegNum)
697  return RegNum.takeError();
699  Row.getCFAValue() =
701  else
702  Row.getCFAValue().setRegister(*RegNum);
703  break;
704  }
705 
706  case dwarf::DW_CFA_def_cfa_offset:
707  case dwarf::DW_CFA_def_cfa_offset_sf: {
708  llvm::Expected<int64_t> Offset = Inst.getOperandAsSigned(CFIP, 0);
709  if (!Offset)
710  return Offset.takeError();
712  return createStringError(
714  "%s found when CFA rule was not RegPlusOffset",
715  CFIP.callFrameString(Inst.Opcode).str().c_str());
716  }
717  Row.getCFAValue().setOffset(*Offset);
718  break;
719  }
720 
721  case dwarf::DW_CFA_def_cfa:
722  case dwarf::DW_CFA_def_cfa_sf: {
723  llvm::Expected<uint64_t> RegNum = Inst.getOperandAsUnsigned(CFIP, 0);
724  if (!RegNum)
725  return RegNum.takeError();
726  llvm::Expected<int64_t> Offset = Inst.getOperandAsSigned(CFIP, 1);
727  if (!Offset)
728  return Offset.takeError();
729  Row.getCFAValue() =
731  break;
732  }
733 
734  case dwarf::DW_CFA_def_cfa_expression:
735  Row.getCFAValue() =
736  UnwindLocation::createIsDWARFExpression(*Inst.Expression);
737  break;
738  }
739  }
740  return Error::success();
741 }
742 
743 ArrayRef<CFIProgram::OperandType[2]> CFIProgram::getOperandTypes() {
744  static OperandType OpTypes[DW_CFA_restore+1][2];
745  static bool Initialized = false;
746  if (Initialized) {
747  return ArrayRef<OperandType[2]>(&OpTypes[0], DW_CFA_restore+1);
748  }
749  Initialized = true;
750 
751 #define DECLARE_OP2(OP, OPTYPE0, OPTYPE1) \
752  do { \
753  OpTypes[OP][0] = OPTYPE0; \
754  OpTypes[OP][1] = OPTYPE1; \
755  } while (false)
756 #define DECLARE_OP1(OP, OPTYPE0) DECLARE_OP2(OP, OPTYPE0, OT_None)
757 #define DECLARE_OP0(OP) DECLARE_OP1(OP, OT_None)
758 
759  DECLARE_OP1(DW_CFA_set_loc, OT_Address);
760  DECLARE_OP1(DW_CFA_advance_loc, OT_FactoredCodeOffset);
761  DECLARE_OP1(DW_CFA_advance_loc1, OT_FactoredCodeOffset);
762  DECLARE_OP1(DW_CFA_advance_loc2, OT_FactoredCodeOffset);
763  DECLARE_OP1(DW_CFA_advance_loc4, OT_FactoredCodeOffset);
764  DECLARE_OP1(DW_CFA_MIPS_advance_loc8, OT_FactoredCodeOffset);
765  DECLARE_OP2(DW_CFA_def_cfa, OT_Register, OT_Offset);
766  DECLARE_OP2(DW_CFA_def_cfa_sf, OT_Register, OT_SignedFactDataOffset);
767  DECLARE_OP1(DW_CFA_def_cfa_register, OT_Register);
768  DECLARE_OP1(DW_CFA_def_cfa_offset, OT_Offset);
769  DECLARE_OP1(DW_CFA_def_cfa_offset_sf, OT_SignedFactDataOffset);
770  DECLARE_OP1(DW_CFA_def_cfa_expression, OT_Expression);
771  DECLARE_OP1(DW_CFA_undefined, OT_Register);
772  DECLARE_OP1(DW_CFA_same_value, OT_Register);
773  DECLARE_OP2(DW_CFA_offset, OT_Register, OT_UnsignedFactDataOffset);
774  DECLARE_OP2(DW_CFA_offset_extended, OT_Register, OT_UnsignedFactDataOffset);
775  DECLARE_OP2(DW_CFA_offset_extended_sf, OT_Register, OT_SignedFactDataOffset);
776  DECLARE_OP2(DW_CFA_val_offset, OT_Register, OT_UnsignedFactDataOffset);
777  DECLARE_OP2(DW_CFA_val_offset_sf, OT_Register, OT_SignedFactDataOffset);
778  DECLARE_OP2(DW_CFA_register, OT_Register, OT_Register);
779  DECLARE_OP2(DW_CFA_expression, OT_Register, OT_Expression);
780  DECLARE_OP2(DW_CFA_val_expression, OT_Register, OT_Expression);
781  DECLARE_OP1(DW_CFA_restore, OT_Register);
782  DECLARE_OP1(DW_CFA_restore_extended, OT_Register);
783  DECLARE_OP0(DW_CFA_remember_state);
784  DECLARE_OP0(DW_CFA_restore_state);
785  DECLARE_OP0(DW_CFA_GNU_window_save);
786  DECLARE_OP1(DW_CFA_GNU_args_size, OT_Offset);
787  DECLARE_OP0(DW_CFA_nop);
788 
789 #undef DECLARE_OP0
790 #undef DECLARE_OP1
791 #undef DECLARE_OP2
792 
793  return ArrayRef<OperandType[2]>(&OpTypes[0], DW_CFA_restore+1);
794 }
795 
796 /// Print \p Opcode's operand number \p OperandIdx which has value \p Operand.
797 void CFIProgram::printOperand(raw_ostream &OS, DIDumpOptions DumpOpts,
798  const MCRegisterInfo *MRI, bool IsEH,
799  const Instruction &Instr, unsigned OperandIdx,
800  uint64_t Operand) const {
801  assert(OperandIdx < 2);
802  uint8_t Opcode = Instr.Opcode;
803  OperandType Type = getOperandTypes()[Opcode][OperandIdx];
804 
805  switch (Type) {
806  case OT_Unset: {
807  OS << " Unsupported " << (OperandIdx ? "second" : "first") << " operand to";
808  auto OpcodeName = callFrameString(Opcode);
809  if (!OpcodeName.empty())
810  OS << " " << OpcodeName;
811  else
812  OS << format(" Opcode %x", Opcode);
813  break;
814  }
815  case OT_None:
816  break;
817  case OT_Address:
818  OS << format(" %" PRIx64, Operand);
819  break;
820  case OT_Offset:
821  // The offsets are all encoded in a unsigned form, but in practice
822  // consumers use them signed. It's most certainly legacy due to
823  // the lack of signed variants in the first Dwarf standards.
824  OS << format(" %+" PRId64, int64_t(Operand));
825  break;
826  case OT_FactoredCodeOffset: // Always Unsigned
827  if (CodeAlignmentFactor)
828  OS << format(" %" PRId64, Operand * CodeAlignmentFactor);
829  else
830  OS << format(" %" PRId64 "*code_alignment_factor" , Operand);
831  break;
832  case OT_SignedFactDataOffset:
833  if (DataAlignmentFactor)
834  OS << format(" %" PRId64, int64_t(Operand) * DataAlignmentFactor);
835  else
836  OS << format(" %" PRId64 "*data_alignment_factor" , int64_t(Operand));
837  break;
838  case OT_UnsignedFactDataOffset:
839  if (DataAlignmentFactor)
840  OS << format(" %" PRId64, Operand * DataAlignmentFactor);
841  else
842  OS << format(" %" PRId64 "*data_alignment_factor" , Operand);
843  break;
844  case OT_Register:
845  OS << ' ';
846  printRegister(OS, MRI, IsEH, Operand);
847  break;
848  case OT_Expression:
849  assert(Instr.Expression && "missing DWARFExpression object");
850  OS << " ";
851  Instr.Expression->print(OS, DumpOpts, MRI, nullptr, IsEH);
852  break;
853  }
854 }
855 
857  const MCRegisterInfo *MRI, bool IsEH,
858  unsigned IndentLevel) const {
859  for (const auto &Instr : Instructions) {
860  uint8_t Opcode = Instr.Opcode;
861  OS.indent(2 * IndentLevel);
862  OS << callFrameString(Opcode) << ":";
863  for (unsigned i = 0; i < Instr.Ops.size(); ++i)
864  printOperand(OS, DumpOpts, MRI, IsEH, Instr, i, Instr.Ops[i]);
865  OS << '\n';
866  }
867 }
868 
869 // Returns the CIE identifier to be used by the requested format.
870 // CIE ids for .debug_frame sections are defined in Section 7.24 of DWARFv5.
871 // For CIE ID in .eh_frame sections see
872 // https://refspecs.linuxfoundation.org/LSB_5.0.0/LSB-Core-generic/LSB-Core-generic/ehframechpt.html
873 constexpr uint64_t getCIEId(bool IsDWARF64, bool IsEH) {
874  if (IsEH)
875  return 0;
876  if (IsDWARF64)
877  return DW64_CIE_ID;
878  return DW_CIE_ID;
879 }
880 
882  const MCRegisterInfo *MRI, bool IsEH) const {
883  // A CIE with a zero length is a terminator entry in the .eh_frame section.
884  if (IsEH && Length == 0) {
885  OS << format("%08" PRIx64, Offset) << " ZERO terminator\n";
886  return;
887  }
888 
889  OS << format("%08" PRIx64, Offset)
890  << format(" %0*" PRIx64, IsDWARF64 ? 16 : 8, Length)
891  << format(" %0*" PRIx64, IsDWARF64 && !IsEH ? 16 : 8,
892  getCIEId(IsDWARF64, IsEH))
893  << " CIE\n"
894  << " Format: " << FormatString(IsDWARF64) << "\n";
895  if (IsEH && Version != 1)
896  OS << "WARNING: unsupported CIE version\n";
897  OS << format(" Version: %d\n", Version)
898  << " Augmentation: \"" << Augmentation << "\"\n";
899  if (Version >= 4) {
900  OS << format(" Address size: %u\n", (uint32_t)AddressSize);
901  OS << format(" Segment desc size: %u\n",
902  (uint32_t)SegmentDescriptorSize);
903  }
904  OS << format(" Code alignment factor: %u\n", (uint32_t)CodeAlignmentFactor);
905  OS << format(" Data alignment factor: %d\n", (int32_t)DataAlignmentFactor);
906  OS << format(" Return address column: %d\n", (int32_t)ReturnAddressRegister);
907  if (Personality)
908  OS << format(" Personality Address: %016" PRIx64 "\n", *Personality);
909  if (!AugmentationData.empty()) {
910  OS << " Augmentation data: ";
911  for (uint8_t Byte : AugmentationData)
912  OS << ' ' << hexdigit(Byte >> 4) << hexdigit(Byte & 0xf);
913  OS << "\n";
914  }
915  OS << "\n";
916  CFIs.dump(OS, DumpOpts, MRI, IsEH);
917  OS << "\n";
918 
919  if (Expected<UnwindTable> RowsOrErr = UnwindTable::create(this))
920  RowsOrErr->dump(OS, MRI, IsEH, 1);
921  else {
924  "decoding the CIE opcodes into rows failed"),
925  RowsOrErr.takeError()));
926  }
927  OS << "\n";
928 }
929 
931  const MCRegisterInfo *MRI, bool IsEH) const {
932  OS << format("%08" PRIx64, Offset)
933  << format(" %0*" PRIx64, IsDWARF64 ? 16 : 8, Length)
934  << format(" %0*" PRIx64, IsDWARF64 && !IsEH ? 16 : 8, CIEPointer)
935  << " FDE cie=";
936  if (LinkedCIE)
937  OS << format("%08" PRIx64, LinkedCIE->getOffset());
938  else
939  OS << "<invalid offset>";
940  OS << format(" pc=%08" PRIx64 "...%08" PRIx64 "\n", InitialLocation,
941  InitialLocation + AddressRange);
942  OS << " Format: " << FormatString(IsDWARF64) << "\n";
943  if (LSDAAddress)
944  OS << format(" LSDA Address: %016" PRIx64 "\n", *LSDAAddress);
945  CFIs.dump(OS, DumpOpts, MRI, IsEH);
946  OS << "\n";
947 
948  if (Expected<UnwindTable> RowsOrErr = UnwindTable::create(this))
949  RowsOrErr->dump(OS, MRI, IsEH, 1);
950  else {
953  "decoding the FDE opcodes into rows failed"),
954  RowsOrErr.takeError()));
955  }
956  OS << "\n";
957 }
958 
960  bool IsEH, uint64_t EHFrameAddress)
961  : Arch(Arch), IsEH(IsEH), EHFrameAddress(EHFrameAddress) {}
962 
964 
966  uint64_t Offset, int Length) {
967  errs() << "DUMP: ";
968  for (int i = 0; i < Length; ++i) {
969  uint8_t c = Data.getU8(&Offset);
970  errs().write_hex(c); errs() << " ";
971  }
972  errs() << "\n";
973 }
974 
976  uint64_t Offset = 0;
978 
979  while (Data.isValidOffset(Offset)) {
980  uint64_t StartOffset = Offset;
981 
982  uint64_t Length;
983  DwarfFormat Format;
984  std::tie(Length, Format) = Data.getInitialLength(&Offset);
985  bool IsDWARF64 = Format == DWARF64;
986 
987  // If the Length is 0, then this CIE is a terminator. We add it because some
988  // dumper tools might need it to print something special for such entries
989  // (e.g. llvm-objdump --dwarf=frames prints "ZERO terminator").
990  if (Length == 0) {
991  auto Cie = std::make_unique<CIE>(
992  IsDWARF64, StartOffset, 0, 0, SmallString<8>(), 0, 0, 0, 0, 0,
993  SmallString<8>(), 0, 0, None, None, Arch);
994  CIEs[StartOffset] = Cie.get();
995  Entries.push_back(std::move(Cie));
996  break;
997  }
998 
999  // At this point, Offset points to the next field after Length.
1000  // Length is the structure size excluding itself. Compute an offset one
1001  // past the end of the structure (needed to know how many instructions to
1002  // read).
1003  uint64_t StartStructureOffset = Offset;
1004  uint64_t EndStructureOffset = Offset + Length;
1005 
1006  // The Id field's size depends on the DWARF format
1007  Error Err = Error::success();
1008  uint64_t Id = Data.getRelocatedValue((IsDWARF64 && !IsEH) ? 8 : 4, &Offset,
1009  /*SectionIndex=*/nullptr, &Err);
1010  if (Err)
1011  return Err;
1012 
1013  if (Id == getCIEId(IsDWARF64, IsEH)) {
1014  uint8_t Version = Data.getU8(&Offset);
1015  const char *Augmentation = Data.getCStr(&Offset);
1016  StringRef AugmentationString(Augmentation ? Augmentation : "");
1017  uint8_t AddressSize = Version < 4 ? Data.getAddressSize() :
1018  Data.getU8(&Offset);
1019  Data.setAddressSize(AddressSize);
1020  uint8_t SegmentDescriptorSize = Version < 4 ? 0 : Data.getU8(&Offset);
1021  uint64_t CodeAlignmentFactor = Data.getULEB128(&Offset);
1022  int64_t DataAlignmentFactor = Data.getSLEB128(&Offset);
1023  uint64_t ReturnAddressRegister =
1024  Version == 1 ? Data.getU8(&Offset) : Data.getULEB128(&Offset);
1025 
1026  // Parse the augmentation data for EH CIEs
1027  StringRef AugmentationData("");
1028  uint32_t FDEPointerEncoding = DW_EH_PE_absptr;
1029  uint32_t LSDAPointerEncoding = DW_EH_PE_omit;
1030  Optional<uint64_t> Personality;
1031  Optional<uint32_t> PersonalityEncoding;
1032  if (IsEH) {
1033  Optional<uint64_t> AugmentationLength;
1034  uint64_t StartAugmentationOffset;
1035  uint64_t EndAugmentationOffset;
1036 
1037  // Walk the augmentation string to get all the augmentation data.
1038  for (unsigned i = 0, e = AugmentationString.size(); i != e; ++i) {
1039  switch (AugmentationString[i]) {
1040  default:
1041  return createStringError(
1043  "unknown augmentation character in entry at 0x%" PRIx64,
1044  StartOffset);
1045  case 'L':
1046  LSDAPointerEncoding = Data.getU8(&Offset);
1047  break;
1048  case 'P': {
1049  if (Personality)
1050  return createStringError(
1052  "duplicate personality in entry at 0x%" PRIx64, StartOffset);
1053  PersonalityEncoding = Data.getU8(&Offset);
1054  Personality = Data.getEncodedPointer(
1055  &Offset, *PersonalityEncoding,
1056  EHFrameAddress ? EHFrameAddress + Offset : 0);
1057  break;
1058  }
1059  case 'R':
1060  FDEPointerEncoding = Data.getU8(&Offset);
1061  break;
1062  case 'S':
1063  // Current frame is a signal trampoline.
1064  break;
1065  case 'z':
1066  if (i)
1067  return createStringError(
1069  "'z' must be the first character at 0x%" PRIx64, StartOffset);
1070  // Parse the augmentation length first. We only parse it if
1071  // the string contains a 'z'.
1072  AugmentationLength = Data.getULEB128(&Offset);
1073  StartAugmentationOffset = Offset;
1074  EndAugmentationOffset = Offset + *AugmentationLength;
1075  break;
1076  case 'B':
1077  // B-Key is used for signing functions associated with this
1078  // augmentation string
1079  break;
1080  }
1081  }
1082 
1083  if (AugmentationLength.hasValue()) {
1084  if (Offset != EndAugmentationOffset)
1086  "parsing augmentation data at 0x%" PRIx64
1087  " failed",
1088  StartOffset);
1089  AugmentationData = Data.getData().slice(StartAugmentationOffset,
1090  EndAugmentationOffset);
1091  }
1092  }
1093 
1094  auto Cie = std::make_unique<CIE>(
1095  IsDWARF64, StartOffset, Length, Version, AugmentationString,
1096  AddressSize, SegmentDescriptorSize, CodeAlignmentFactor,
1097  DataAlignmentFactor, ReturnAddressRegister, AugmentationData,
1098  FDEPointerEncoding, LSDAPointerEncoding, Personality,
1099  PersonalityEncoding, Arch);
1100  CIEs[StartOffset] = Cie.get();
1101  Entries.emplace_back(std::move(Cie));
1102  } else {
1103  // FDE
1104  uint64_t CIEPointer = Id;
1105  uint64_t InitialLocation = 0;
1106  uint64_t AddressRange = 0;
1107  Optional<uint64_t> LSDAAddress;
1108  CIE *Cie = CIEs[IsEH ? (StartStructureOffset - CIEPointer) : CIEPointer];
1109 
1110  if (IsEH) {
1111  // The address size is encoded in the CIE we reference.
1112  if (!Cie)
1114  "parsing FDE data at 0x%" PRIx64
1115  " failed due to missing CIE",
1116  StartOffset);
1117  if (auto Val =
1118  Data.getEncodedPointer(&Offset, Cie->getFDEPointerEncoding(),
1119  EHFrameAddress + Offset)) {
1120  InitialLocation = *Val;
1121  }
1122  if (auto Val = Data.getEncodedPointer(
1123  &Offset, Cie->getFDEPointerEncoding(), 0)) {
1124  AddressRange = *Val;
1125  }
1126 
1127  StringRef AugmentationString = Cie->getAugmentationString();
1128  if (!AugmentationString.empty()) {
1129  // Parse the augmentation length and data for this FDE.
1130  uint64_t AugmentationLength = Data.getULEB128(&Offset);
1131 
1132  uint64_t EndAugmentationOffset = Offset + AugmentationLength;
1133 
1134  // Decode the LSDA if the CIE augmentation string said we should.
1135  if (Cie->getLSDAPointerEncoding() != DW_EH_PE_omit) {
1136  LSDAAddress = Data.getEncodedPointer(
1137  &Offset, Cie->getLSDAPointerEncoding(),
1138  EHFrameAddress ? Offset + EHFrameAddress : 0);
1139  }
1140 
1141  if (Offset != EndAugmentationOffset)
1143  "parsing augmentation data at 0x%" PRIx64
1144  " failed",
1145  StartOffset);
1146  }
1147  } else {
1148  InitialLocation = Data.getRelocatedAddress(&Offset);
1149  AddressRange = Data.getRelocatedAddress(&Offset);
1150  }
1151 
1152  Entries.emplace_back(new FDE(IsDWARF64, StartOffset, Length, CIEPointer,
1153  InitialLocation, AddressRange, Cie,
1154  LSDAAddress, Arch));
1155  }
1156 
1157  if (Error E =
1158  Entries.back()->cfis().parse(Data, &Offset, EndStructureOffset))
1159  return E;
1160 
1161  if (Offset != EndStructureOffset)
1162  return createStringError(
1164  "parsing entry instructions at 0x%" PRIx64 " failed", StartOffset);
1165  }
1166 
1167  return Error::success();
1168 }
1169 
1170 FrameEntry *DWARFDebugFrame::getEntryAtOffset(uint64_t Offset) const {
1171  auto It = partition_point(Entries, [=](const std::unique_ptr<FrameEntry> &E) {
1172  return E->getOffset() < Offset;
1173  });
1174  if (It != Entries.end() && (*It)->getOffset() == Offset)
1175  return It->get();
1176  return nullptr;
1177 }
1178 
1180  const MCRegisterInfo *MRI,
1181  Optional<uint64_t> Offset) const {
1182  if (Offset) {
1183  if (auto *Entry = getEntryAtOffset(*Offset))
1184  Entry->dump(OS, DumpOpts, MRI, IsEH);
1185  return;
1186  }
1187 
1188  OS << "\n";
1189  for (const auto &Entry : Entries)
1190  Entry->dump(OS, DumpOpts, MRI, IsEH);
1191 }
llvm::dwarf::UnwindLocation::Undefined
@ Undefined
Register is not available and can't be recovered.
Definition: DWARFDebugFrame.h:40
i
i
Definition: README.txt:29
DWARF_CFI_PRIMARY_OPCODE_MASK
const uint8_t DWARF_CFI_PRIMARY_OPCODE_MASK
Definition: DWARFDebugFrame.cpp:231
llvm::dwarf::RegisterLocations::getRegisterLocation
Optional< UnwindLocation > getRegisterLocation(uint32_t RegNum) const
Return the location for the register in RegNum if there is a location.
Definition: DWARFDebugFrame.h:174
llvm::errc::invalid_argument
@ invalid_argument
DECLARE_OP0
#define DECLARE_OP0(OP)
llvm
Definition: AllocatorList.h:23
llvm::dwarf::FDE
DWARF Frame Description Entry (FDE)
Definition: DWARFDebugFrame.h:599
llvm::StringRef::empty
LLVM_NODISCARD bool empty() const
empty - Check if the string is empty.
Definition: StringRef.h:156
Optional.h
llvm::dwarf::UnwindRow::hasAddress
bool hasAddress() const
Returns true if the address is valid in this object.
Definition: DWARFDebugFrame.h:248
llvm::dwarf::UnwindRow::getAddress
uint64_t getAddress() const
Get the address for this row.
Definition: DWARFDebugFrame.h:254
StringRef.h
llvm::dwarf::CFIProgram::Instruction
An instruction consists of a DWARF CFI opcode and an optional sequence of operands.
Definition: DWARFDebugFrame.h:396
dumpDataAux
static void LLVM_ATTRIBUTE_UNUSED dumpDataAux(DataExtractor Data, uint64_t Offset, int Length)
Definition: DWARFDebugFrame.cpp:965
ErrorHandling.h
llvm::Error::success
static ErrorSuccess success()
Create a success value.
Definition: Error.h:332
llvm::dwarf::UnwindLocation::Constant
@ Constant
Value is a constant value contained in "Offset": reg = Offset.
Definition: DWARFDebugFrame.h:60
llvm::dwarf::UnwindLocation::createAtDWARFExpression
static UnwindLocation createAtDWARFExpression(DWARFExpression Expr)
Definition: DWARFDebugFrame.cpp:76
llvm::dwarf::UnwindLocation::setRegister
void setRegister(uint32_t NewRegNum)
Some opcodes will modify the CFA location's register only, so we need to be able to modify the CFA re...
Definition: DWARFDebugFrame.h:126
Errc.h
llvm::dwarf::UnwindTable
A class that contains all UnwindRow objects for an FDE or a single unwind row for a CIE.
Definition: DWARFDebugFrame.h:303
llvm::Type
The instances of the Type class are immutable: once they are created, they are never changed.
Definition: Type.h:46
DenseMap.h
llvm::dwarf::CFIProgram::Instruction::Opcode
uint8_t Opcode
Definition: DWARFDebugFrame.h:399
llvm::dwarf::UnwindLocation::operator==
bool operator==(const UnwindLocation &RHS) const
Definition: DWARFDebugFrame.cpp:127
llvm::dwarf::UnwindLocation::Same
@ Same
Register value is in the register, nothing needs to be done to unwind it: reg = reg.
Definition: DWARFDebugFrame.h:44
llvm::Optional< unsigned >
Offset
uint64_t Offset
Definition: ELFObjHandler.cpp:81
llvm::dwarf::UnwindLocation::createIsCFAPlusOffset
static UnwindLocation createIsCFAPlusOffset(int32_t Off)
Create a location that is in (Deref == false) or at (Deref == true) the CFA plus an offset.
Definition: DWARFDebugFrame.cpp:55
llvm::errs
raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
Definition: raw_ostream.cpp:894
llvm::Expected
Tagged union holding either a T or a Error.
Definition: APFloat.h:42
llvm::dwarf::CFIProgram::addInstruction
void addInstruction(const Instruction &I)
Definition: DWARFDebugFrame.h:441
llvm::DWARFDataExtractor
A DataExtractor (typically for an in-memory copy of an object-file section) plus a relocation map for...
Definition: DWARFDataExtractor.h:21
LLVM_ATTRIBUTE_UNUSED
#define LLVM_ATTRIBUTE_UNUSED
Definition: Compiler.h:188
llvm::Triple::aarch64_32
@ aarch64_32
Definition: Triple.h:54
Format.h
llvm::dwarf::UnwindLocation::createUndefined
static UnwindLocation createUndefined()
Create a location where the value is undefined and not available.
Definition: DWARFDebugFrame.cpp:47
llvm::dwarf::UnwindLocation::createIsRegisterPlusOffset
static UnwindLocation createIsRegisterPlusOffset(uint32_t Reg, int32_t Off)
Create a location where the saved value is in (Deref == false) or at (Deref == true) a regiser plus a...
Definition: DWARFDebugFrame.cpp:63
llvm::dwarf::UnwindTable::create
static Expected< UnwindTable > create(const CIE *Cie)
Create an UnwindTable from a Common Information Entry (CIE).
Definition: DWARFDebugFrame.cpp:221
llvm::Data
@ Data
Definition: SIMachineScheduler.h:56
llvm::Optional::hasValue
constexpr bool hasValue() const
Definition: Optional.h:286
ENUM_TO_CSTR
#define ENUM_TO_CSTR(e)
llvm::dwarf::FDE::getInitialLocation
uint64_t getInitialLocation() const
Definition: DWARFDebugFrame.h:614
llvm::dwarf::CallFrameString
StringRef CallFrameString(unsigned Encoding, Triple::ArchType Arch)
Definition: Dwarf.cpp:536
llvm::Triple::sparc
@ sparc
Definition: Triple.h:75
llvm::Triple::sparcv9
@ sparcv9
Definition: Triple.h:76
llvm::Triple::sparcel
@ sparcel
Definition: Triple.h:77
llvm::Triple::ArchType
ArchType
Definition: Triple.h:47
getCIEId
constexpr uint64_t getCIEId(bool IsDWARF64, bool IsEH)
Definition: DWARFDebugFrame.cpp:873
DWARFDebugFrame.h
E
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
llvm::dwarf::UnwindLocation::DWARFExpr
@ DWARFExpr
Register value is in or at a value found by evaluating a DWARF expression: reg = eval(dwarf_expr) reg...
Definition: DWARFDebugFrame.h:57
C
(vector float) vec_cmpeq(*A, *B) C
Definition: README_ALTIVEC.txt:86
llvm::dwarf::UnwindRow::setAddress
void setAddress(uint64_t Addr)
Set the address for this UnwindRow.
Definition: DWARFDebugFrame.h:260
llvm::dwarf::UnwindRow
A class that represents a single row in the unwind table that is decoded by parsing the DWARF Call Fr...
Definition: DWARFDebugFrame.h:237
First
into llvm powi allowing the code generator to produce balanced multiplication trees First
Definition: README.txt:54
llvm::dwarf::RegisterLocations::hasLocations
bool hasLocations() const
Returns true if we have any register locations in this object.
Definition: DWARFDebugFrame.h:210
llvm::dwarf::UnwindLocation::createIsDWARFExpression
static UnwindLocation createIsDWARFExpression(DWARFExpression Expr)
Create a location whose value is the result of evaluating a DWARF expression.
Definition: DWARFDebugFrame.cpp:72
llvm::Instruction
Definition: Instruction.h:45
llvm::dwarf::FormatString
StringRef FormatString(DwarfFormat Format)
Definition: Dwarf.cpp:790
llvm::dwarf::CFIProgram::codeAlign
uint64_t codeAlign() const
Definition: DWARFDebugFrame.h:422
llvm::raw_ostream
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition: raw_ostream.h:50
llvm::dwarf::CFIProgram::dataAlign
int64_t dataAlign() const
Definition: DWARFDebugFrame.h:423
llvm::IndexedInstrProf::Version
const uint64_t Version
Definition: InstrProf.h:991
llvm::dwarf::CIE::getFDEPointerEncoding
uint32_t getFDEPointerEncoding() const
Definition: DWARFDebugFrame.h:573
llvm::dwarf::UnwindLocation
A class that represents a location for the Call Frame Address (CFA) or a register.
Definition: DWARFDebugFrame.h:34
llvm::dwarf::DwarfFormat
DwarfFormat
Constants that define the DWARF format as 32 or 64 bit.
Definition: Dwarf.h:92
c
the resulting code requires compare and branches when and if the revised code is with conditional branches instead of More there is a byte word extend before each where there should be only and the condition codes are not remembered when the same two values are compared twice More LSR enhancements i8 and i32 load store addressing modes are identical int int c
Definition: README.txt:418
llvm::StringRef::str
LLVM_NODISCARD std::string str() const
str - Get the contents as an std::string.
Definition: StringRef.h:248
llvm::DWARFDebugFrame::parse
Error parse(DWARFDataExtractor Data)
Parse the section from raw data.
Definition: DWARFDebugFrame.cpp:975
llvm::None
const NoneType None
Definition: None.h:23
llvm::dwarf::InvalidRegisterNumber
constexpr uint32_t InvalidRegisterNumber
Definition: DWARFDebugFrame.h:29
llvm::dwarf::UnwindLocation::getLocation
Location getLocation() const
Definition: DWARFDebugFrame.h:119
llvm::SmallString< 8 >
llvm::dwarf::UnwindLocation::Unspecified
@ Unspecified
Not specified.
Definition: DWARFDebugFrame.h:38
llvm::dwarf::UnwindRow::getCFAValue
UnwindLocation & getCFAValue()
Definition: DWARFDebugFrame.h:269
DWARF_CFI_PRIMARY_OPERAND_MASK
const uint8_t DWARF_CFI_PRIMARY_OPERAND_MASK
Definition: DWARFDebugFrame.cpp:232
llvm::errc::illegal_byte_sequence
@ illegal_byte_sequence
llvm::dwarf::CFIProgram::Instruction::Ops
Operands Ops
Definition: DWARFDebugFrame.h:400
DECLARE_OP1
#define DECLARE_OP1(OP, OPTYPE0)
llvm::dwarf::RegisterLocations
A class that can track all registers with locations in a UnwindRow object.
Definition: DWARFDebugFrame.h:164
llvm::RISCVFenceField::O
@ O
Definition: RISCVBaseInfo.h:128
llvm::dwarf::RegisterLocations::dump
void dump(raw_ostream &OS, const MCRegisterInfo *MRI, bool IsEH) const
Dump all registers + locations that are currently defined in this object.
Definition: DWARFDebugFrame.cpp:148
DECLARE_OP2
#define DECLARE_OP2(OP, OPTYPE0, OPTYPE1)
llvm::dwarf::RegisterLocations::setRegisterLocation
void setRegisterLocation(uint32_t RegNum, const UnwindLocation &Location)
Set the location for the register in RegNum to Location.
Definition: DWARFDebugFrame.h:186
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::dwarf::UnwindLocation::setOffset
void setOffset(int32_t NewOffset)
Some opcodes will modify the CFA location's offset only, so we need to be able to modify the CFA regi...
Definition: DWARFDebugFrame.h:130
llvm::numbers::e
constexpr double e
Definition: MathExtras.h:58
llvm::DenseMap
Definition: DenseMap.h:714
StringExtras.h
llvm::dwarf::UnwindLocation::createAtCFAPlusOffset
static UnwindLocation createAtCFAPlusOffset(int32_t Off)
Definition: DWARFDebugFrame.cpp:59
MCRegisterInfo.h
llvm::joinErrors
Error joinErrors(Error E1, Error E2)
Concatenate errors.
Definition: Error.h:429
llvm::DWARFExpression
Definition: DWARFExpression.h:25
llvm::Value::print
void print(raw_ostream &O, bool IsForDebug=false) const
Implement operator<< on Value.
Definition: AsmWriter.cpp:4614
llvm::dwarf::UnwindLocation::CFAPlusOffset
@ CFAPlusOffset
Register is in or at the CFA plus an offset: reg = CFA + offset reg = defef(CFA + offset)
Definition: DWARFDebugFrame.h:48
assert
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
llvm::dwarf::CFIProgram
Represent a sequence of Call Frame Information instructions that, when read in order,...
Definition: DWARFDebugFrame.h:389
llvm::dwarf::UnwindLocation::createAtRegisterPlusOffset
static UnwindLocation createAtRegisterPlusOffset(uint32_t Reg, int32_t Off)
Definition: DWARFDebugFrame.cpp:67
llvm::dwarf::UnwindLocation::createSame
static UnwindLocation createSame()
Create a location where the value is known to be in the register itself.
Definition: DWARFDebugFrame.cpp:49
llvm::dwarf::CFIProgram::callFrameString
StringRef callFrameString(unsigned Opcode) const
Get a DWARF CFI call frame string for the given DW_CFA opcode.
Definition: DWARFDebugFrame.cpp:362
llvm::DataExtractor::Cursor
A class representing a position in a DataExtractor, as well as any error encountered during extractio...
Definition: DataExtractor.h:54
llvm::dwarf::UnwindRow::getRegisterLocations
RegisterLocations & getRegisterLocations()
Definition: DWARFDebugFrame.h:271
llvm::Expression
Class representing an expression and its matching format.
Definition: FileCheckImpl.h:238
llvm::dwarf::CIE::getLSDAPointerEncoding
uint32_t getLSDAPointerEncoding() const
Definition: DWARFDebugFrame.h:575
llvm::ArrayRef
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition: APInt.h:32
llvm::dwarf::FrameEntry::cfis
const CFIProgram & cfis() const
Definition: DWARFDebugFrame.h:518
llvm::dwarf::CIE::dump
void dump(raw_ostream &OS, DIDumpOptions DumpOpts, const MCRegisterInfo *MRI, bool IsEH) const override
Dump the instructions in this CFI fragment.
Definition: DWARFDebugFrame.cpp:881
llvm::Triple::aarch64_be
@ aarch64_be
Definition: Triple.h:53
llvm::StringRef
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:57
Dwarf.h
llvm::errc::not_supported
@ not_supported
llvm_unreachable
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
Definition: ErrorHandling.h:136
llvm::dwarf::UnwindLocation::createIsConstant
static UnwindLocation createIsConstant(int32_t Value)
Definition: DWARFDebugFrame.cpp:51
uint32_t
Compiler.h
llvm::dwarf::UnwindTable::dump
void dump(raw_ostream &OS, const MCRegisterInfo *MRI, bool IsEH, unsigned IndentLevel=0) const
Dump the UnwindTable to the stream.
Definition: DWARFDebugFrame.cpp:187
llvm::DWARFDebugFrame::DWARFDebugFrame
DWARFDebugFrame(Triple::ArchType Arch, bool IsEH=false, uint64_t EHFrameAddress=0)
Definition: DWARFDebugFrame.cpp:959
llvm::dwarf::CFIProgram::Instruction::getOperandAsUnsigned
Expected< uint64_t > getOperandAsUnsigned(const CFIProgram &CFIP, uint32_t OperandIdx) const
Definition: DWARFDebugFrame.cpp:385
llvm::format
format_object< Ts... > format(const char *Fmt, const Ts &... Vals)
These are helper functions used to produce formatted output.
Definition: Format.h:124
llvm::MCRegisterInfo
MCRegisterInfo base class - We assume that the target defines a static array of MCRegisterDesc object...
Definition: MCRegisterInfo.h:135
llvm::dwarf::CIE::getAugmentationString
StringRef getAugmentationString() const
Definition: DWARFDebugFrame.h:565
MRI
unsigned const MachineRegisterInfo * MRI
Definition: AArch64AdvSIMDScalarPass.cpp:105
llvm::dwarf::DW_EH_PE_absptr
@ DW_EH_PE_absptr
Definition: Dwarf.h:432
llvm::partition_point
auto partition_point(R &&Range, Predicate P)
Binary search for the first iterator in a range where a predicate is false.
Definition: STLExtras.h:1653
llvm::createStringError
Error createStringError(std::error_code EC, char const *Fmt, const Ts &... Vals)
Create formatted StringError object.
Definition: Error.h:1202
llvm::dwarf::operator<<
raw_ostream & operator<<(raw_ostream &OS, const UnwindLocation &R)
Definition: DWARFDebugFrame.cpp:121
llvm::dwarf::UnwindLocation::dump
void dump(raw_ostream &OS, const MCRegisterInfo *MRI, bool IsEH) const
Dump a location expression as text and use the register information if some is provided.
Definition: DWARFDebugFrame.cpp:80
llvm::dwarf::DW_CIE_ID
const uint32_t DW_CIE_ID
Special ID values that distinguish a CIE from a FDE in DWARF CFI.
Definition: Dwarf.h:97
llvm::dwarf::FDE::getLinkedCIE
const CIE * getLinkedCIE() const
Definition: DWARFDebugFrame.h:613
llvm::Error
Lightweight error class with error context and mandatory checking.
Definition: Error.h:157
llvm::DWARFDebugFrame::dump
void dump(raw_ostream &OS, DIDumpOptions DumpOpts, const MCRegisterInfo *MRI, Optional< uint64_t > Offset) const
Dump the section data into the given stream.
Definition: DWARFDebugFrame.cpp:1179
llvm::dwarf::CIE
DWARF Common Information Entry (CIE)
Definition: DWARFDebugFrame.h:540
Casting.h
DataExtractor.h
llvm::dwarf::FDE::dump
void dump(raw_ostream &OS, DIDumpOptions DumpOpts, const MCRegisterInfo *MRI, bool IsEH) const override
Dump the instructions in this CFI fragment.
Definition: DWARFDebugFrame.cpp:930
llvm::TargetStackID::Value
Value
Definition: TargetFrameLowering.h:27
llvm::dwarf::FrameEntry
An entry in either debug_frame or eh_frame.
Definition: DWARFDebugFrame.h:504
llvm::dwarf::UnwindLocation::createUnspecified
static UnwindLocation createUnspecified()
Create a location whose rule is set to Unspecified.
Definition: DWARFDebugFrame.cpp:45
llvm::dwarf::UnwindRow::dump
void dump(raw_ostream &OS, const MCRegisterInfo *MRI, bool IsEH, unsigned IndentLevel=0) const
Dump the UnwindRow to the stream.
Definition: DWARFDebugFrame.cpp:168
llvm::dwarf::UnwindRow::slideAddress
void slideAddress(uint64_t Offset)
Offset the address for this UnwindRow.
Definition: DWARFDebugFrame.h:268
printRegister
static void printRegister(raw_ostream &OS, const MCRegisterInfo *MRI, bool IsEH, unsigned RegNum)
Definition: DWARFDebugFrame.cpp:32
llvm::Expected::takeError
Error takeError()
Take ownership of the stored error.
Definition: Error.h:557
llvm::dwarf::CFIProgram::Instruction::getOperandAsSigned
Expected< int64_t > getOperandAsSigned(const CFIProgram &CFIP, uint32_t OperandIdx) const
Definition: DWARFDebugFrame.cpp:429
llvm::DataExtractor
Definition: DataExtractor.h:41
llvm::raw_ostream::indent
raw_ostream & indent(unsigned NumSpaces)
indent - Insert 'NumSpaces' spaces.
Definition: raw_ostream.cpp:497
llvm::dwarf::UnwindLocation::RegPlusOffset
@ RegPlusOffset
Register it in or at a register plus offset: reg = reg + offset reg = deref(reg + offset)
Definition: DWARFDebugFrame.h:52
llvm::dwarf::DW_EH_PE_omit
@ DW_EH_PE_omit
Definition: Dwarf.h:433
llvm::Triple::getArchTypeName
static StringRef getArchTypeName(ArchType Kind)
getArchTypeName - Get the canonical name for the Kind architecture.
Definition: Triple.cpp:23
RegName
#define RegName(no)
llvm::dwarf::RegisterLocations::removeRegisterLocation
void removeRegisterLocation(uint32_t RegNum)
Removes any rule for the register in RegNum.
Definition: DWARFDebugFrame.h:194
llvm::dwarf::DWARF64
@ DWARF64
Definition: Dwarf.h:92
llvm::dwarf::CFIProgram::dump
void dump(raw_ostream &OS, DIDumpOptions DumpOpts, const MCRegisterInfo *MRI, bool IsEH, unsigned IndentLevel=1) const
Definition: DWARFDebugFrame.cpp:856
llvm::dwarf::DW64_CIE_ID
const uint64_t DW64_CIE_ID
Definition: Dwarf.h:98
raw_ostream.h
llvm::AMDGPU::VGPRIndexMode::Id
Id
Definition: SIDefines.h:221
llvm::DWARFDebugFrame::~DWARFDebugFrame
~DWARFDebugFrame()
llvm::StringRef::size
LLVM_NODISCARD size_t size() const
size - Get the string size.
Definition: StringRef.h:160
llvm::Value
LLVM Value Representation.
Definition: Value.h:75
llvm::dwarf::FDE::getAddressRange
uint64_t getAddressRange() const
Definition: DWARFDebugFrame.h:615
llvm::Triple::aarch64
@ aarch64
Definition: Triple.h:52
llvm::dwarf::CFIProgram::parse
Error parse(DWARFDataExtractor Data, uint64_t *Offset, uint64_t EndOffset)
Parse and store a sequence of CFI instructions from Data, starting at *Offset and ending at EndOffset...
Definition: DWARFDebugFrame.cpp:234
llvm::dwarf::FrameEntry::getOffset
uint64_t getOffset() const
Definition: DWARFDebugFrame.h:516
llvm::DIDumpOptions
Container for dump options that control which debug information will be dumped.
Definition: DIContext.h:187
llvm::raw_ostream::write_hex
raw_ostream & write_hex(unsigned long long N)
Output N in hexadecimal, without any prefix or padding.
Definition: raw_ostream.cpp:140
llvm::DIDumpOptions::RecoverableErrorHandler
std::function< void(Error)> RecoverableErrorHandler
Definition: DIContext.h:219