xref: /freebsd-src/contrib/llvm-project/llvm/lib/DebugInfo/DWARF/DWARFDebugFrame.cpp (revision 0b57cec536236d46e3dba9bd041533462f33dbb7)
1*0b57cec5SDimitry Andric //===- DWARFDebugFrame.h - Parsing of .debug_frame ------------------------===//
2*0b57cec5SDimitry Andric //
3*0b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*0b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5*0b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*0b57cec5SDimitry Andric //
7*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
8*0b57cec5SDimitry Andric 
9*0b57cec5SDimitry Andric #include "llvm/DebugInfo/DWARF/DWARFDebugFrame.h"
10*0b57cec5SDimitry Andric #include "llvm/ADT/DenseMap.h"
11*0b57cec5SDimitry Andric #include "llvm/ADT/Optional.h"
12*0b57cec5SDimitry Andric #include "llvm/ADT/StringExtras.h"
13*0b57cec5SDimitry Andric #include "llvm/ADT/StringRef.h"
14*0b57cec5SDimitry Andric #include "llvm/BinaryFormat/Dwarf.h"
15*0b57cec5SDimitry Andric #include "llvm/Support/Casting.h"
16*0b57cec5SDimitry Andric #include "llvm/Support/Compiler.h"
17*0b57cec5SDimitry Andric #include "llvm/Support/DataExtractor.h"
18*0b57cec5SDimitry Andric #include "llvm/Support/Errc.h"
19*0b57cec5SDimitry Andric #include "llvm/Support/ErrorHandling.h"
20*0b57cec5SDimitry Andric #include "llvm/Support/Format.h"
21*0b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h"
22*0b57cec5SDimitry Andric #include <algorithm>
23*0b57cec5SDimitry Andric #include <cassert>
24*0b57cec5SDimitry Andric #include <cinttypes>
25*0b57cec5SDimitry Andric #include <cstdint>
26*0b57cec5SDimitry Andric #include <string>
27*0b57cec5SDimitry Andric #include <vector>
28*0b57cec5SDimitry Andric 
29*0b57cec5SDimitry Andric using namespace llvm;
30*0b57cec5SDimitry Andric using namespace dwarf;
31*0b57cec5SDimitry Andric 
32*0b57cec5SDimitry Andric 
33*0b57cec5SDimitry Andric // See DWARF standard v3, section 7.23
34*0b57cec5SDimitry Andric const uint8_t DWARF_CFI_PRIMARY_OPCODE_MASK = 0xc0;
35*0b57cec5SDimitry Andric const uint8_t DWARF_CFI_PRIMARY_OPERAND_MASK = 0x3f;
36*0b57cec5SDimitry Andric 
37*0b57cec5SDimitry Andric Error CFIProgram::parse(DWARFDataExtractor Data, uint32_t *Offset,
38*0b57cec5SDimitry Andric                         uint32_t EndOffset) {
39*0b57cec5SDimitry Andric   while (*Offset < EndOffset) {
40*0b57cec5SDimitry Andric     uint8_t Opcode = Data.getRelocatedValue(1, Offset);
41*0b57cec5SDimitry Andric     // Some instructions have a primary opcode encoded in the top bits.
42*0b57cec5SDimitry Andric     uint8_t Primary = Opcode & DWARF_CFI_PRIMARY_OPCODE_MASK;
43*0b57cec5SDimitry Andric 
44*0b57cec5SDimitry Andric     if (Primary) {
45*0b57cec5SDimitry Andric       // If it's a primary opcode, the first operand is encoded in the bottom
46*0b57cec5SDimitry Andric       // bits of the opcode itself.
47*0b57cec5SDimitry Andric       uint64_t Op1 = Opcode & DWARF_CFI_PRIMARY_OPERAND_MASK;
48*0b57cec5SDimitry Andric       switch (Primary) {
49*0b57cec5SDimitry Andric       default:
50*0b57cec5SDimitry Andric         return createStringError(errc::illegal_byte_sequence,
51*0b57cec5SDimitry Andric                                  "Invalid primary CFI opcode 0x%" PRIx8,
52*0b57cec5SDimitry Andric                                  Primary);
53*0b57cec5SDimitry Andric       case DW_CFA_advance_loc:
54*0b57cec5SDimitry Andric       case DW_CFA_restore:
55*0b57cec5SDimitry Andric         addInstruction(Primary, Op1);
56*0b57cec5SDimitry Andric         break;
57*0b57cec5SDimitry Andric       case DW_CFA_offset:
58*0b57cec5SDimitry Andric         addInstruction(Primary, Op1, Data.getULEB128(Offset));
59*0b57cec5SDimitry Andric         break;
60*0b57cec5SDimitry Andric       }
61*0b57cec5SDimitry Andric     } else {
62*0b57cec5SDimitry Andric       // Extended opcode - its value is Opcode itself.
63*0b57cec5SDimitry Andric       switch (Opcode) {
64*0b57cec5SDimitry Andric       default:
65*0b57cec5SDimitry Andric         return createStringError(errc::illegal_byte_sequence,
66*0b57cec5SDimitry Andric                                  "Invalid extended CFI opcode 0x%" PRIx8,
67*0b57cec5SDimitry Andric                                  Opcode);
68*0b57cec5SDimitry Andric       case DW_CFA_nop:
69*0b57cec5SDimitry Andric       case DW_CFA_remember_state:
70*0b57cec5SDimitry Andric       case DW_CFA_restore_state:
71*0b57cec5SDimitry Andric       case DW_CFA_GNU_window_save:
72*0b57cec5SDimitry Andric         // No operands
73*0b57cec5SDimitry Andric         addInstruction(Opcode);
74*0b57cec5SDimitry Andric         break;
75*0b57cec5SDimitry Andric       case DW_CFA_set_loc:
76*0b57cec5SDimitry Andric         // Operands: Address
77*0b57cec5SDimitry Andric         addInstruction(Opcode, Data.getRelocatedAddress(Offset));
78*0b57cec5SDimitry Andric         break;
79*0b57cec5SDimitry Andric       case DW_CFA_advance_loc1:
80*0b57cec5SDimitry Andric         // Operands: 1-byte delta
81*0b57cec5SDimitry Andric         addInstruction(Opcode, Data.getRelocatedValue(1, Offset));
82*0b57cec5SDimitry Andric         break;
83*0b57cec5SDimitry Andric       case DW_CFA_advance_loc2:
84*0b57cec5SDimitry Andric         // Operands: 2-byte delta
85*0b57cec5SDimitry Andric         addInstruction(Opcode, Data.getRelocatedValue(2, Offset));
86*0b57cec5SDimitry Andric         break;
87*0b57cec5SDimitry Andric       case DW_CFA_advance_loc4:
88*0b57cec5SDimitry Andric         // Operands: 4-byte delta
89*0b57cec5SDimitry Andric         addInstruction(Opcode, Data.getRelocatedValue(4, Offset));
90*0b57cec5SDimitry Andric         break;
91*0b57cec5SDimitry Andric       case DW_CFA_restore_extended:
92*0b57cec5SDimitry Andric       case DW_CFA_undefined:
93*0b57cec5SDimitry Andric       case DW_CFA_same_value:
94*0b57cec5SDimitry Andric       case DW_CFA_def_cfa_register:
95*0b57cec5SDimitry Andric       case DW_CFA_def_cfa_offset:
96*0b57cec5SDimitry Andric       case DW_CFA_GNU_args_size:
97*0b57cec5SDimitry Andric         // Operands: ULEB128
98*0b57cec5SDimitry Andric         addInstruction(Opcode, Data.getULEB128(Offset));
99*0b57cec5SDimitry Andric         break;
100*0b57cec5SDimitry Andric       case DW_CFA_def_cfa_offset_sf:
101*0b57cec5SDimitry Andric         // Operands: SLEB128
102*0b57cec5SDimitry Andric         addInstruction(Opcode, Data.getSLEB128(Offset));
103*0b57cec5SDimitry Andric         break;
104*0b57cec5SDimitry Andric       case DW_CFA_offset_extended:
105*0b57cec5SDimitry Andric       case DW_CFA_register:
106*0b57cec5SDimitry Andric       case DW_CFA_def_cfa:
107*0b57cec5SDimitry Andric       case DW_CFA_val_offset: {
108*0b57cec5SDimitry Andric         // Operands: ULEB128, ULEB128
109*0b57cec5SDimitry Andric         // Note: We can not embed getULEB128 directly into function
110*0b57cec5SDimitry Andric         // argument list. getULEB128 changes Offset and order of evaluation
111*0b57cec5SDimitry Andric         // for arguments is unspecified.
112*0b57cec5SDimitry Andric         auto op1 = Data.getULEB128(Offset);
113*0b57cec5SDimitry Andric         auto op2 = Data.getULEB128(Offset);
114*0b57cec5SDimitry Andric         addInstruction(Opcode, op1, op2);
115*0b57cec5SDimitry Andric         break;
116*0b57cec5SDimitry Andric         }
117*0b57cec5SDimitry Andric         case DW_CFA_offset_extended_sf:
118*0b57cec5SDimitry Andric         case DW_CFA_def_cfa_sf:
119*0b57cec5SDimitry Andric         case DW_CFA_val_offset_sf: {
120*0b57cec5SDimitry Andric           // Operands: ULEB128, SLEB128
121*0b57cec5SDimitry Andric           // Note: see comment for the previous case
122*0b57cec5SDimitry Andric           auto op1 = Data.getULEB128(Offset);
123*0b57cec5SDimitry Andric           auto op2 = (uint64_t)Data.getSLEB128(Offset);
124*0b57cec5SDimitry Andric           addInstruction(Opcode, op1, op2);
125*0b57cec5SDimitry Andric           break;
126*0b57cec5SDimitry Andric         }
127*0b57cec5SDimitry Andric         case DW_CFA_def_cfa_expression: {
128*0b57cec5SDimitry Andric           uint32_t ExprLength = Data.getULEB128(Offset);
129*0b57cec5SDimitry Andric           addInstruction(Opcode, 0);
130*0b57cec5SDimitry Andric           DataExtractor Extractor(
131*0b57cec5SDimitry Andric               Data.getData().slice(*Offset, *Offset + ExprLength),
132*0b57cec5SDimitry Andric               Data.isLittleEndian(), Data.getAddressSize());
133*0b57cec5SDimitry Andric           Instructions.back().Expression = DWARFExpression(
134*0b57cec5SDimitry Andric               Extractor, Data.getAddressSize(), dwarf::DWARF_VERSION);
135*0b57cec5SDimitry Andric           *Offset += ExprLength;
136*0b57cec5SDimitry Andric           break;
137*0b57cec5SDimitry Andric         }
138*0b57cec5SDimitry Andric         case DW_CFA_expression:
139*0b57cec5SDimitry Andric         case DW_CFA_val_expression: {
140*0b57cec5SDimitry Andric           auto RegNum = Data.getULEB128(Offset);
141*0b57cec5SDimitry Andric           auto BlockLength = Data.getULEB128(Offset);
142*0b57cec5SDimitry Andric           addInstruction(Opcode, RegNum, 0);
143*0b57cec5SDimitry Andric           DataExtractor Extractor(
144*0b57cec5SDimitry Andric               Data.getData().slice(*Offset, *Offset + BlockLength),
145*0b57cec5SDimitry Andric               Data.isLittleEndian(), Data.getAddressSize());
146*0b57cec5SDimitry Andric           Instructions.back().Expression = DWARFExpression(
147*0b57cec5SDimitry Andric               Extractor, Data.getAddressSize(), dwarf::DWARF_VERSION);
148*0b57cec5SDimitry Andric           *Offset += BlockLength;
149*0b57cec5SDimitry Andric           break;
150*0b57cec5SDimitry Andric         }
151*0b57cec5SDimitry Andric       }
152*0b57cec5SDimitry Andric     }
153*0b57cec5SDimitry Andric   }
154*0b57cec5SDimitry Andric 
155*0b57cec5SDimitry Andric   return Error::success();
156*0b57cec5SDimitry Andric }
157*0b57cec5SDimitry Andric 
158*0b57cec5SDimitry Andric namespace {
159*0b57cec5SDimitry Andric 
160*0b57cec5SDimitry Andric 
161*0b57cec5SDimitry Andric } // end anonymous namespace
162*0b57cec5SDimitry Andric 
163*0b57cec5SDimitry Andric ArrayRef<CFIProgram::OperandType[2]> CFIProgram::getOperandTypes() {
164*0b57cec5SDimitry Andric   static OperandType OpTypes[DW_CFA_restore+1][2];
165*0b57cec5SDimitry Andric   static bool Initialized = false;
166*0b57cec5SDimitry Andric   if (Initialized) {
167*0b57cec5SDimitry Andric     return ArrayRef<OperandType[2]>(&OpTypes[0], DW_CFA_restore+1);
168*0b57cec5SDimitry Andric   }
169*0b57cec5SDimitry Andric   Initialized = true;
170*0b57cec5SDimitry Andric 
171*0b57cec5SDimitry Andric #define DECLARE_OP2(OP, OPTYPE0, OPTYPE1)       \
172*0b57cec5SDimitry Andric   do {                                          \
173*0b57cec5SDimitry Andric     OpTypes[OP][0] = OPTYPE0;                   \
174*0b57cec5SDimitry Andric     OpTypes[OP][1] = OPTYPE1;                   \
175*0b57cec5SDimitry Andric   } while (false)
176*0b57cec5SDimitry Andric #define DECLARE_OP1(OP, OPTYPE0) DECLARE_OP2(OP, OPTYPE0, OT_None)
177*0b57cec5SDimitry Andric #define DECLARE_OP0(OP) DECLARE_OP1(OP, OT_None)
178*0b57cec5SDimitry Andric 
179*0b57cec5SDimitry Andric   DECLARE_OP1(DW_CFA_set_loc, OT_Address);
180*0b57cec5SDimitry Andric   DECLARE_OP1(DW_CFA_advance_loc, OT_FactoredCodeOffset);
181*0b57cec5SDimitry Andric   DECLARE_OP1(DW_CFA_advance_loc1, OT_FactoredCodeOffset);
182*0b57cec5SDimitry Andric   DECLARE_OP1(DW_CFA_advance_loc2, OT_FactoredCodeOffset);
183*0b57cec5SDimitry Andric   DECLARE_OP1(DW_CFA_advance_loc4, OT_FactoredCodeOffset);
184*0b57cec5SDimitry Andric   DECLARE_OP1(DW_CFA_MIPS_advance_loc8, OT_FactoredCodeOffset);
185*0b57cec5SDimitry Andric   DECLARE_OP2(DW_CFA_def_cfa, OT_Register, OT_Offset);
186*0b57cec5SDimitry Andric   DECLARE_OP2(DW_CFA_def_cfa_sf, OT_Register, OT_SignedFactDataOffset);
187*0b57cec5SDimitry Andric   DECLARE_OP1(DW_CFA_def_cfa_register, OT_Register);
188*0b57cec5SDimitry Andric   DECLARE_OP1(DW_CFA_def_cfa_offset, OT_Offset);
189*0b57cec5SDimitry Andric   DECLARE_OP1(DW_CFA_def_cfa_offset_sf, OT_SignedFactDataOffset);
190*0b57cec5SDimitry Andric   DECLARE_OP1(DW_CFA_def_cfa_expression, OT_Expression);
191*0b57cec5SDimitry Andric   DECLARE_OP1(DW_CFA_undefined, OT_Register);
192*0b57cec5SDimitry Andric   DECLARE_OP1(DW_CFA_same_value, OT_Register);
193*0b57cec5SDimitry Andric   DECLARE_OP2(DW_CFA_offset, OT_Register, OT_UnsignedFactDataOffset);
194*0b57cec5SDimitry Andric   DECLARE_OP2(DW_CFA_offset_extended, OT_Register, OT_UnsignedFactDataOffset);
195*0b57cec5SDimitry Andric   DECLARE_OP2(DW_CFA_offset_extended_sf, OT_Register, OT_SignedFactDataOffset);
196*0b57cec5SDimitry Andric   DECLARE_OP2(DW_CFA_val_offset, OT_Register, OT_UnsignedFactDataOffset);
197*0b57cec5SDimitry Andric   DECLARE_OP2(DW_CFA_val_offset_sf, OT_Register, OT_SignedFactDataOffset);
198*0b57cec5SDimitry Andric   DECLARE_OP2(DW_CFA_register, OT_Register, OT_Register);
199*0b57cec5SDimitry Andric   DECLARE_OP2(DW_CFA_expression, OT_Register, OT_Expression);
200*0b57cec5SDimitry Andric   DECLARE_OP2(DW_CFA_val_expression, OT_Register, OT_Expression);
201*0b57cec5SDimitry Andric   DECLARE_OP1(DW_CFA_restore, OT_Register);
202*0b57cec5SDimitry Andric   DECLARE_OP1(DW_CFA_restore_extended, OT_Register);
203*0b57cec5SDimitry Andric   DECLARE_OP0(DW_CFA_remember_state);
204*0b57cec5SDimitry Andric   DECLARE_OP0(DW_CFA_restore_state);
205*0b57cec5SDimitry Andric   DECLARE_OP0(DW_CFA_GNU_window_save);
206*0b57cec5SDimitry Andric   DECLARE_OP1(DW_CFA_GNU_args_size, OT_Offset);
207*0b57cec5SDimitry Andric   DECLARE_OP0(DW_CFA_nop);
208*0b57cec5SDimitry Andric 
209*0b57cec5SDimitry Andric #undef DECLARE_OP0
210*0b57cec5SDimitry Andric #undef DECLARE_OP1
211*0b57cec5SDimitry Andric #undef DECLARE_OP2
212*0b57cec5SDimitry Andric 
213*0b57cec5SDimitry Andric   return ArrayRef<OperandType[2]>(&OpTypes[0], DW_CFA_restore+1);
214*0b57cec5SDimitry Andric }
215*0b57cec5SDimitry Andric 
216*0b57cec5SDimitry Andric /// Print \p Opcode's operand number \p OperandIdx which has value \p Operand.
217*0b57cec5SDimitry Andric void CFIProgram::printOperand(raw_ostream &OS, const MCRegisterInfo *MRI,
218*0b57cec5SDimitry Andric                               bool IsEH, const Instruction &Instr,
219*0b57cec5SDimitry Andric                               unsigned OperandIdx, uint64_t Operand) const {
220*0b57cec5SDimitry Andric   assert(OperandIdx < 2);
221*0b57cec5SDimitry Andric   uint8_t Opcode = Instr.Opcode;
222*0b57cec5SDimitry Andric   OperandType Type = getOperandTypes()[Opcode][OperandIdx];
223*0b57cec5SDimitry Andric 
224*0b57cec5SDimitry Andric   switch (Type) {
225*0b57cec5SDimitry Andric   case OT_Unset: {
226*0b57cec5SDimitry Andric     OS << " Unsupported " << (OperandIdx ? "second" : "first") << " operand to";
227*0b57cec5SDimitry Andric     auto OpcodeName = CallFrameString(Opcode, Arch);
228*0b57cec5SDimitry Andric     if (!OpcodeName.empty())
229*0b57cec5SDimitry Andric       OS << " " << OpcodeName;
230*0b57cec5SDimitry Andric     else
231*0b57cec5SDimitry Andric       OS << format(" Opcode %x",  Opcode);
232*0b57cec5SDimitry Andric     break;
233*0b57cec5SDimitry Andric   }
234*0b57cec5SDimitry Andric   case OT_None:
235*0b57cec5SDimitry Andric     break;
236*0b57cec5SDimitry Andric   case OT_Address:
237*0b57cec5SDimitry Andric     OS << format(" %" PRIx64, Operand);
238*0b57cec5SDimitry Andric     break;
239*0b57cec5SDimitry Andric   case OT_Offset:
240*0b57cec5SDimitry Andric     // The offsets are all encoded in a unsigned form, but in practice
241*0b57cec5SDimitry Andric     // consumers use them signed. It's most certainly legacy due to
242*0b57cec5SDimitry Andric     // the lack of signed variants in the first Dwarf standards.
243*0b57cec5SDimitry Andric     OS << format(" %+" PRId64, int64_t(Operand));
244*0b57cec5SDimitry Andric     break;
245*0b57cec5SDimitry Andric   case OT_FactoredCodeOffset: // Always Unsigned
246*0b57cec5SDimitry Andric     if (CodeAlignmentFactor)
247*0b57cec5SDimitry Andric       OS << format(" %" PRId64, Operand * CodeAlignmentFactor);
248*0b57cec5SDimitry Andric     else
249*0b57cec5SDimitry Andric       OS << format(" %" PRId64 "*code_alignment_factor" , Operand);
250*0b57cec5SDimitry Andric     break;
251*0b57cec5SDimitry Andric   case OT_SignedFactDataOffset:
252*0b57cec5SDimitry Andric     if (DataAlignmentFactor)
253*0b57cec5SDimitry Andric       OS << format(" %" PRId64, int64_t(Operand) * DataAlignmentFactor);
254*0b57cec5SDimitry Andric     else
255*0b57cec5SDimitry Andric       OS << format(" %" PRId64 "*data_alignment_factor" , int64_t(Operand));
256*0b57cec5SDimitry Andric     break;
257*0b57cec5SDimitry Andric   case OT_UnsignedFactDataOffset:
258*0b57cec5SDimitry Andric     if (DataAlignmentFactor)
259*0b57cec5SDimitry Andric       OS << format(" %" PRId64, Operand * DataAlignmentFactor);
260*0b57cec5SDimitry Andric     else
261*0b57cec5SDimitry Andric       OS << format(" %" PRId64 "*data_alignment_factor" , Operand);
262*0b57cec5SDimitry Andric     break;
263*0b57cec5SDimitry Andric   case OT_Register:
264*0b57cec5SDimitry Andric     OS << format(" reg%" PRId64, Operand);
265*0b57cec5SDimitry Andric     break;
266*0b57cec5SDimitry Andric   case OT_Expression:
267*0b57cec5SDimitry Andric     assert(Instr.Expression && "missing DWARFExpression object");
268*0b57cec5SDimitry Andric     OS << " ";
269*0b57cec5SDimitry Andric     Instr.Expression->print(OS, MRI, nullptr, IsEH);
270*0b57cec5SDimitry Andric     break;
271*0b57cec5SDimitry Andric   }
272*0b57cec5SDimitry Andric }
273*0b57cec5SDimitry Andric 
274*0b57cec5SDimitry Andric void CFIProgram::dump(raw_ostream &OS, const MCRegisterInfo *MRI, bool IsEH,
275*0b57cec5SDimitry Andric                       unsigned IndentLevel) const {
276*0b57cec5SDimitry Andric   for (const auto &Instr : Instructions) {
277*0b57cec5SDimitry Andric     uint8_t Opcode = Instr.Opcode;
278*0b57cec5SDimitry Andric     if (Opcode & DWARF_CFI_PRIMARY_OPCODE_MASK)
279*0b57cec5SDimitry Andric       Opcode &= DWARF_CFI_PRIMARY_OPCODE_MASK;
280*0b57cec5SDimitry Andric     OS.indent(2 * IndentLevel);
281*0b57cec5SDimitry Andric     OS << CallFrameString(Opcode, Arch) << ":";
282*0b57cec5SDimitry Andric     for (unsigned i = 0; i < Instr.Ops.size(); ++i)
283*0b57cec5SDimitry Andric       printOperand(OS, MRI, IsEH, Instr, i, Instr.Ops[i]);
284*0b57cec5SDimitry Andric     OS << '\n';
285*0b57cec5SDimitry Andric   }
286*0b57cec5SDimitry Andric }
287*0b57cec5SDimitry Andric 
288*0b57cec5SDimitry Andric void CIE::dump(raw_ostream &OS, const MCRegisterInfo *MRI, bool IsEH) const {
289*0b57cec5SDimitry Andric   OS << format("%08x %08x %08x CIE", (uint32_t)Offset, (uint32_t)Length,
290*0b57cec5SDimitry Andric                DW_CIE_ID)
291*0b57cec5SDimitry Andric      << "\n";
292*0b57cec5SDimitry Andric   OS << format("  Version:               %d\n", Version);
293*0b57cec5SDimitry Andric   OS << "  Augmentation:          \"" << Augmentation << "\"\n";
294*0b57cec5SDimitry Andric   if (Version >= 4) {
295*0b57cec5SDimitry Andric     OS << format("  Address size:          %u\n", (uint32_t)AddressSize);
296*0b57cec5SDimitry Andric     OS << format("  Segment desc size:     %u\n",
297*0b57cec5SDimitry Andric                  (uint32_t)SegmentDescriptorSize);
298*0b57cec5SDimitry Andric   }
299*0b57cec5SDimitry Andric   OS << format("  Code alignment factor: %u\n", (uint32_t)CodeAlignmentFactor);
300*0b57cec5SDimitry Andric   OS << format("  Data alignment factor: %d\n", (int32_t)DataAlignmentFactor);
301*0b57cec5SDimitry Andric   OS << format("  Return address column: %d\n", (int32_t)ReturnAddressRegister);
302*0b57cec5SDimitry Andric   if (Personality)
303*0b57cec5SDimitry Andric     OS << format("  Personality Address: %016" PRIx64 "\n", *Personality);
304*0b57cec5SDimitry Andric   if (!AugmentationData.empty()) {
305*0b57cec5SDimitry Andric     OS << "  Augmentation data:    ";
306*0b57cec5SDimitry Andric     for (uint8_t Byte : AugmentationData)
307*0b57cec5SDimitry Andric       OS << ' ' << hexdigit(Byte >> 4) << hexdigit(Byte & 0xf);
308*0b57cec5SDimitry Andric     OS << "\n";
309*0b57cec5SDimitry Andric   }
310*0b57cec5SDimitry Andric   OS << "\n";
311*0b57cec5SDimitry Andric   CFIs.dump(OS, MRI, IsEH);
312*0b57cec5SDimitry Andric   OS << "\n";
313*0b57cec5SDimitry Andric }
314*0b57cec5SDimitry Andric 
315*0b57cec5SDimitry Andric void FDE::dump(raw_ostream &OS, const MCRegisterInfo *MRI, bool IsEH) const {
316*0b57cec5SDimitry Andric   OS << format("%08x %08x %08x FDE ", (uint32_t)Offset, (uint32_t)Length,
317*0b57cec5SDimitry Andric                (int32_t)LinkedCIEOffset);
318*0b57cec5SDimitry Andric   OS << format("cie=%08x pc=%08x...%08x\n", (int32_t)LinkedCIEOffset,
319*0b57cec5SDimitry Andric                (uint32_t)InitialLocation,
320*0b57cec5SDimitry Andric                (uint32_t)InitialLocation + (uint32_t)AddressRange);
321*0b57cec5SDimitry Andric   if (LSDAAddress)
322*0b57cec5SDimitry Andric     OS << format("  LSDA Address: %016" PRIx64 "\n", *LSDAAddress);
323*0b57cec5SDimitry Andric   CFIs.dump(OS, MRI, IsEH);
324*0b57cec5SDimitry Andric   OS << "\n";
325*0b57cec5SDimitry Andric }
326*0b57cec5SDimitry Andric 
327*0b57cec5SDimitry Andric DWARFDebugFrame::DWARFDebugFrame(Triple::ArchType Arch,
328*0b57cec5SDimitry Andric     bool IsEH, uint64_t EHFrameAddress)
329*0b57cec5SDimitry Andric     : Arch(Arch), IsEH(IsEH), EHFrameAddress(EHFrameAddress) {}
330*0b57cec5SDimitry Andric 
331*0b57cec5SDimitry Andric DWARFDebugFrame::~DWARFDebugFrame() = default;
332*0b57cec5SDimitry Andric 
333*0b57cec5SDimitry Andric static void LLVM_ATTRIBUTE_UNUSED dumpDataAux(DataExtractor Data,
334*0b57cec5SDimitry Andric                                               uint32_t Offset, int Length) {
335*0b57cec5SDimitry Andric   errs() << "DUMP: ";
336*0b57cec5SDimitry Andric   for (int i = 0; i < Length; ++i) {
337*0b57cec5SDimitry Andric     uint8_t c = Data.getU8(&Offset);
338*0b57cec5SDimitry Andric     errs().write_hex(c); errs() << " ";
339*0b57cec5SDimitry Andric   }
340*0b57cec5SDimitry Andric   errs() << "\n";
341*0b57cec5SDimitry Andric }
342*0b57cec5SDimitry Andric 
343*0b57cec5SDimitry Andric // This is a workaround for old compilers which do not allow
344*0b57cec5SDimitry Andric // noreturn attribute usage in lambdas. Once the support for those
345*0b57cec5SDimitry Andric // compilers are phased out, we can remove this and return back to
346*0b57cec5SDimitry Andric // a ReportError lambda: [StartOffset](const char *ErrorMsg).
347*0b57cec5SDimitry Andric static void LLVM_ATTRIBUTE_NORETURN ReportError(uint32_t StartOffset,
348*0b57cec5SDimitry Andric                                                 const char *ErrorMsg) {
349*0b57cec5SDimitry Andric   std::string Str;
350*0b57cec5SDimitry Andric   raw_string_ostream OS(Str);
351*0b57cec5SDimitry Andric   OS << format(ErrorMsg, StartOffset);
352*0b57cec5SDimitry Andric   OS.flush();
353*0b57cec5SDimitry Andric   report_fatal_error(Str);
354*0b57cec5SDimitry Andric }
355*0b57cec5SDimitry Andric 
356*0b57cec5SDimitry Andric void DWARFDebugFrame::parse(DWARFDataExtractor Data) {
357*0b57cec5SDimitry Andric   uint32_t Offset = 0;
358*0b57cec5SDimitry Andric   DenseMap<uint32_t, CIE *> CIEs;
359*0b57cec5SDimitry Andric 
360*0b57cec5SDimitry Andric   while (Data.isValidOffset(Offset)) {
361*0b57cec5SDimitry Andric     uint32_t StartOffset = Offset;
362*0b57cec5SDimitry Andric 
363*0b57cec5SDimitry Andric     bool IsDWARF64 = false;
364*0b57cec5SDimitry Andric     uint64_t Length = Data.getRelocatedValue(4, &Offset);
365*0b57cec5SDimitry Andric     uint64_t Id;
366*0b57cec5SDimitry Andric 
367*0b57cec5SDimitry Andric     if (Length == UINT32_MAX) {
368*0b57cec5SDimitry Andric       // DWARF-64 is distinguished by the first 32 bits of the initial length
369*0b57cec5SDimitry Andric       // field being 0xffffffff. Then, the next 64 bits are the actual entry
370*0b57cec5SDimitry Andric       // length.
371*0b57cec5SDimitry Andric       IsDWARF64 = true;
372*0b57cec5SDimitry Andric       Length = Data.getRelocatedValue(8, &Offset);
373*0b57cec5SDimitry Andric     }
374*0b57cec5SDimitry Andric 
375*0b57cec5SDimitry Andric     // At this point, Offset points to the next field after Length.
376*0b57cec5SDimitry Andric     // Length is the structure size excluding itself. Compute an offset one
377*0b57cec5SDimitry Andric     // past the end of the structure (needed to know how many instructions to
378*0b57cec5SDimitry Andric     // read).
379*0b57cec5SDimitry Andric     // TODO: For honest DWARF64 support, DataExtractor will have to treat
380*0b57cec5SDimitry Andric     //       offset_ptr as uint64_t*
381*0b57cec5SDimitry Andric     uint32_t StartStructureOffset = Offset;
382*0b57cec5SDimitry Andric     uint32_t EndStructureOffset = Offset + static_cast<uint32_t>(Length);
383*0b57cec5SDimitry Andric 
384*0b57cec5SDimitry Andric     // The Id field's size depends on the DWARF format
385*0b57cec5SDimitry Andric     Id = Data.getUnsigned(&Offset, (IsDWARF64 && !IsEH) ? 8 : 4);
386*0b57cec5SDimitry Andric     bool IsCIE =
387*0b57cec5SDimitry Andric         ((IsDWARF64 && Id == DW64_CIE_ID) || Id == DW_CIE_ID || (IsEH && !Id));
388*0b57cec5SDimitry Andric 
389*0b57cec5SDimitry Andric     if (IsCIE) {
390*0b57cec5SDimitry Andric       uint8_t Version = Data.getU8(&Offset);
391*0b57cec5SDimitry Andric       const char *Augmentation = Data.getCStr(&Offset);
392*0b57cec5SDimitry Andric       StringRef AugmentationString(Augmentation ? Augmentation : "");
393*0b57cec5SDimitry Andric       uint8_t AddressSize = Version < 4 ? Data.getAddressSize() :
394*0b57cec5SDimitry Andric                                           Data.getU8(&Offset);
395*0b57cec5SDimitry Andric       Data.setAddressSize(AddressSize);
396*0b57cec5SDimitry Andric       uint8_t SegmentDescriptorSize = Version < 4 ? 0 : Data.getU8(&Offset);
397*0b57cec5SDimitry Andric       uint64_t CodeAlignmentFactor = Data.getULEB128(&Offset);
398*0b57cec5SDimitry Andric       int64_t DataAlignmentFactor = Data.getSLEB128(&Offset);
399*0b57cec5SDimitry Andric       uint64_t ReturnAddressRegister =
400*0b57cec5SDimitry Andric           Version == 1 ? Data.getU8(&Offset) : Data.getULEB128(&Offset);
401*0b57cec5SDimitry Andric 
402*0b57cec5SDimitry Andric       // Parse the augmentation data for EH CIEs
403*0b57cec5SDimitry Andric       StringRef AugmentationData("");
404*0b57cec5SDimitry Andric       uint32_t FDEPointerEncoding = DW_EH_PE_absptr;
405*0b57cec5SDimitry Andric       uint32_t LSDAPointerEncoding = DW_EH_PE_omit;
406*0b57cec5SDimitry Andric       Optional<uint64_t> Personality;
407*0b57cec5SDimitry Andric       Optional<uint32_t> PersonalityEncoding;
408*0b57cec5SDimitry Andric       if (IsEH) {
409*0b57cec5SDimitry Andric         Optional<uint64_t> AugmentationLength;
410*0b57cec5SDimitry Andric         uint32_t StartAugmentationOffset;
411*0b57cec5SDimitry Andric         uint32_t EndAugmentationOffset;
412*0b57cec5SDimitry Andric 
413*0b57cec5SDimitry Andric         // Walk the augmentation string to get all the augmentation data.
414*0b57cec5SDimitry Andric         for (unsigned i = 0, e = AugmentationString.size(); i != e; ++i) {
415*0b57cec5SDimitry Andric           switch (AugmentationString[i]) {
416*0b57cec5SDimitry Andric             default:
417*0b57cec5SDimitry Andric               ReportError(StartOffset,
418*0b57cec5SDimitry Andric                           "Unknown augmentation character in entry at %lx");
419*0b57cec5SDimitry Andric             case 'L':
420*0b57cec5SDimitry Andric               LSDAPointerEncoding = Data.getU8(&Offset);
421*0b57cec5SDimitry Andric               break;
422*0b57cec5SDimitry Andric             case 'P': {
423*0b57cec5SDimitry Andric               if (Personality)
424*0b57cec5SDimitry Andric                 ReportError(StartOffset,
425*0b57cec5SDimitry Andric                             "Duplicate personality in entry at %lx");
426*0b57cec5SDimitry Andric               PersonalityEncoding = Data.getU8(&Offset);
427*0b57cec5SDimitry Andric               Personality = Data.getEncodedPointer(
428*0b57cec5SDimitry Andric                   &Offset, *PersonalityEncoding,
429*0b57cec5SDimitry Andric                   EHFrameAddress ? EHFrameAddress + Offset : 0);
430*0b57cec5SDimitry Andric               break;
431*0b57cec5SDimitry Andric             }
432*0b57cec5SDimitry Andric             case 'R':
433*0b57cec5SDimitry Andric               FDEPointerEncoding = Data.getU8(&Offset);
434*0b57cec5SDimitry Andric               break;
435*0b57cec5SDimitry Andric             case 'S':
436*0b57cec5SDimitry Andric               // Current frame is a signal trampoline.
437*0b57cec5SDimitry Andric               break;
438*0b57cec5SDimitry Andric             case 'z':
439*0b57cec5SDimitry Andric               if (i)
440*0b57cec5SDimitry Andric                 ReportError(StartOffset,
441*0b57cec5SDimitry Andric                             "'z' must be the first character at %lx");
442*0b57cec5SDimitry Andric               // Parse the augmentation length first.  We only parse it if
443*0b57cec5SDimitry Andric               // the string contains a 'z'.
444*0b57cec5SDimitry Andric               AugmentationLength = Data.getULEB128(&Offset);
445*0b57cec5SDimitry Andric               StartAugmentationOffset = Offset;
446*0b57cec5SDimitry Andric               EndAugmentationOffset = Offset +
447*0b57cec5SDimitry Andric                 static_cast<uint32_t>(*AugmentationLength);
448*0b57cec5SDimitry Andric               break;
449*0b57cec5SDimitry Andric             case 'B':
450*0b57cec5SDimitry Andric               // B-Key is used for signing functions associated with this
451*0b57cec5SDimitry Andric               // augmentation string
452*0b57cec5SDimitry Andric               break;
453*0b57cec5SDimitry Andric           }
454*0b57cec5SDimitry Andric         }
455*0b57cec5SDimitry Andric 
456*0b57cec5SDimitry Andric         if (AugmentationLength.hasValue()) {
457*0b57cec5SDimitry Andric           if (Offset != EndAugmentationOffset)
458*0b57cec5SDimitry Andric             ReportError(StartOffset, "Parsing augmentation data at %lx failed");
459*0b57cec5SDimitry Andric 
460*0b57cec5SDimitry Andric           AugmentationData = Data.getData().slice(StartAugmentationOffset,
461*0b57cec5SDimitry Andric                                                   EndAugmentationOffset);
462*0b57cec5SDimitry Andric         }
463*0b57cec5SDimitry Andric       }
464*0b57cec5SDimitry Andric 
465*0b57cec5SDimitry Andric       auto Cie = llvm::make_unique<CIE>(
466*0b57cec5SDimitry Andric           StartOffset, Length, Version, AugmentationString, AddressSize,
467*0b57cec5SDimitry Andric           SegmentDescriptorSize, CodeAlignmentFactor, DataAlignmentFactor,
468*0b57cec5SDimitry Andric           ReturnAddressRegister, AugmentationData, FDEPointerEncoding,
469*0b57cec5SDimitry Andric           LSDAPointerEncoding, Personality, PersonalityEncoding, Arch);
470*0b57cec5SDimitry Andric       CIEs[StartOffset] = Cie.get();
471*0b57cec5SDimitry Andric       Entries.emplace_back(std::move(Cie));
472*0b57cec5SDimitry Andric     } else {
473*0b57cec5SDimitry Andric       // FDE
474*0b57cec5SDimitry Andric       uint64_t CIEPointer = Id;
475*0b57cec5SDimitry Andric       uint64_t InitialLocation = 0;
476*0b57cec5SDimitry Andric       uint64_t AddressRange = 0;
477*0b57cec5SDimitry Andric       Optional<uint64_t> LSDAAddress;
478*0b57cec5SDimitry Andric       CIE *Cie = CIEs[IsEH ? (StartStructureOffset - CIEPointer) : CIEPointer];
479*0b57cec5SDimitry Andric 
480*0b57cec5SDimitry Andric       if (IsEH) {
481*0b57cec5SDimitry Andric         // The address size is encoded in the CIE we reference.
482*0b57cec5SDimitry Andric         if (!Cie)
483*0b57cec5SDimitry Andric           ReportError(StartOffset,
484*0b57cec5SDimitry Andric                       "Parsing FDE data at %lx failed due to missing CIE");
485*0b57cec5SDimitry Andric 
486*0b57cec5SDimitry Andric         if (auto Val = Data.getEncodedPointer(
487*0b57cec5SDimitry Andric                 &Offset, Cie->getFDEPointerEncoding(),
488*0b57cec5SDimitry Andric                 EHFrameAddress ? EHFrameAddress + Offset : 0)) {
489*0b57cec5SDimitry Andric           InitialLocation = *Val;
490*0b57cec5SDimitry Andric         }
491*0b57cec5SDimitry Andric         if (auto Val = Data.getEncodedPointer(
492*0b57cec5SDimitry Andric                 &Offset, Cie->getFDEPointerEncoding(), 0)) {
493*0b57cec5SDimitry Andric           AddressRange = *Val;
494*0b57cec5SDimitry Andric         }
495*0b57cec5SDimitry Andric 
496*0b57cec5SDimitry Andric         StringRef AugmentationString = Cie->getAugmentationString();
497*0b57cec5SDimitry Andric         if (!AugmentationString.empty()) {
498*0b57cec5SDimitry Andric           // Parse the augmentation length and data for this FDE.
499*0b57cec5SDimitry Andric           uint64_t AugmentationLength = Data.getULEB128(&Offset);
500*0b57cec5SDimitry Andric 
501*0b57cec5SDimitry Andric           uint32_t EndAugmentationOffset =
502*0b57cec5SDimitry Andric             Offset + static_cast<uint32_t>(AugmentationLength);
503*0b57cec5SDimitry Andric 
504*0b57cec5SDimitry Andric           // Decode the LSDA if the CIE augmentation string said we should.
505*0b57cec5SDimitry Andric           if (Cie->getLSDAPointerEncoding() != DW_EH_PE_omit) {
506*0b57cec5SDimitry Andric             LSDAAddress = Data.getEncodedPointer(
507*0b57cec5SDimitry Andric                 &Offset, Cie->getLSDAPointerEncoding(),
508*0b57cec5SDimitry Andric                 EHFrameAddress ? Offset + EHFrameAddress : 0);
509*0b57cec5SDimitry Andric           }
510*0b57cec5SDimitry Andric 
511*0b57cec5SDimitry Andric           if (Offset != EndAugmentationOffset)
512*0b57cec5SDimitry Andric             ReportError(StartOffset, "Parsing augmentation data at %lx failed");
513*0b57cec5SDimitry Andric         }
514*0b57cec5SDimitry Andric       } else {
515*0b57cec5SDimitry Andric         InitialLocation = Data.getRelocatedAddress(&Offset);
516*0b57cec5SDimitry Andric         AddressRange = Data.getRelocatedAddress(&Offset);
517*0b57cec5SDimitry Andric       }
518*0b57cec5SDimitry Andric 
519*0b57cec5SDimitry Andric       Entries.emplace_back(new FDE(StartOffset, Length, CIEPointer,
520*0b57cec5SDimitry Andric                                    InitialLocation, AddressRange,
521*0b57cec5SDimitry Andric                                    Cie, LSDAAddress, Arch));
522*0b57cec5SDimitry Andric     }
523*0b57cec5SDimitry Andric 
524*0b57cec5SDimitry Andric     if (Error E =
525*0b57cec5SDimitry Andric             Entries.back()->cfis().parse(Data, &Offset, EndStructureOffset)) {
526*0b57cec5SDimitry Andric       report_fatal_error(toString(std::move(E)));
527*0b57cec5SDimitry Andric     }
528*0b57cec5SDimitry Andric 
529*0b57cec5SDimitry Andric     if (Offset != EndStructureOffset)
530*0b57cec5SDimitry Andric       ReportError(StartOffset, "Parsing entry instructions at %lx failed");
531*0b57cec5SDimitry Andric   }
532*0b57cec5SDimitry Andric }
533*0b57cec5SDimitry Andric 
534*0b57cec5SDimitry Andric FrameEntry *DWARFDebugFrame::getEntryAtOffset(uint64_t Offset) const {
535*0b57cec5SDimitry Andric   auto It = partition_point(Entries, [=](const std::unique_ptr<FrameEntry> &E) {
536*0b57cec5SDimitry Andric     return E->getOffset() < Offset;
537*0b57cec5SDimitry Andric   });
538*0b57cec5SDimitry Andric   if (It != Entries.end() && (*It)->getOffset() == Offset)
539*0b57cec5SDimitry Andric     return It->get();
540*0b57cec5SDimitry Andric   return nullptr;
541*0b57cec5SDimitry Andric }
542*0b57cec5SDimitry Andric 
543*0b57cec5SDimitry Andric void DWARFDebugFrame::dump(raw_ostream &OS, const MCRegisterInfo *MRI,
544*0b57cec5SDimitry Andric                            Optional<uint64_t> Offset) const {
545*0b57cec5SDimitry Andric   if (Offset) {
546*0b57cec5SDimitry Andric     if (auto *Entry = getEntryAtOffset(*Offset))
547*0b57cec5SDimitry Andric       Entry->dump(OS, MRI, IsEH);
548*0b57cec5SDimitry Andric     return;
549*0b57cec5SDimitry Andric   }
550*0b57cec5SDimitry Andric 
551*0b57cec5SDimitry Andric   OS << "\n";
552*0b57cec5SDimitry Andric   for (const auto &Entry : Entries)
553*0b57cec5SDimitry Andric     Entry->dump(OS, MRI, IsEH);
554*0b57cec5SDimitry Andric }
555