1f4a2713aSLionel Sambuc //===-- DWARFDebugFrame.h - Parsing of .debug_frame -------------*- C++ -*-===//
2f4a2713aSLionel Sambuc //
3f4a2713aSLionel Sambuc //                     The LLVM Compiler Infrastructure
4f4a2713aSLionel Sambuc //
5f4a2713aSLionel Sambuc // This file is distributed under the University of Illinois Open Source
6f4a2713aSLionel Sambuc // License. See LICENSE.TXT for details.
7f4a2713aSLionel Sambuc //
8f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===//
9f4a2713aSLionel Sambuc 
10*0a6a1f1dSLionel Sambuc #include "llvm/DebugInfo/DWARFDebugFrame.h"
11f4a2713aSLionel Sambuc #include "llvm/ADT/SmallString.h"
12f4a2713aSLionel Sambuc #include "llvm/Support/DataTypes.h"
13f4a2713aSLionel Sambuc #include "llvm/Support/Dwarf.h"
14*0a6a1f1dSLionel Sambuc #include "llvm/Support/ErrorHandling.h"
15f4a2713aSLionel Sambuc #include "llvm/Support/Format.h"
16f4a2713aSLionel Sambuc #include "llvm/Support/raw_ostream.h"
17f4a2713aSLionel Sambuc #include <string>
18f4a2713aSLionel Sambuc #include <vector>
19f4a2713aSLionel Sambuc 
20f4a2713aSLionel Sambuc using namespace llvm;
21f4a2713aSLionel Sambuc using namespace dwarf;
22f4a2713aSLionel Sambuc 
23f4a2713aSLionel Sambuc 
24f4a2713aSLionel Sambuc /// \brief Abstract frame entry defining the common interface concrete
25f4a2713aSLionel Sambuc /// entries implement.
26f4a2713aSLionel Sambuc class llvm::FrameEntry {
27f4a2713aSLionel Sambuc public:
28f4a2713aSLionel Sambuc   enum FrameKind {FK_CIE, FK_FDE};
FrameEntry(FrameKind K,uint64_t Offset,uint64_t Length)29*0a6a1f1dSLionel Sambuc   FrameEntry(FrameKind K, uint64_t Offset, uint64_t Length)
30*0a6a1f1dSLionel Sambuc       : Kind(K), Offset(Offset), Length(Length) {}
31f4a2713aSLionel Sambuc 
~FrameEntry()32f4a2713aSLionel Sambuc   virtual ~FrameEntry() {
33f4a2713aSLionel Sambuc   }
34f4a2713aSLionel Sambuc 
getKind() const35f4a2713aSLionel Sambuc   FrameKind getKind() const { return Kind; }
getOffset() const36f4a2713aSLionel Sambuc   virtual uint64_t getOffset() const { return Offset; }
37f4a2713aSLionel Sambuc 
38*0a6a1f1dSLionel Sambuc   /// \brief Parse and store a sequence of CFI instructions from Data,
39*0a6a1f1dSLionel Sambuc   /// starting at *Offset and ending at EndOffset. If everything
40f4a2713aSLionel Sambuc   /// goes well, *Offset should be equal to EndOffset when this method
41f4a2713aSLionel Sambuc   /// returns. Otherwise, an error occurred.
42*0a6a1f1dSLionel Sambuc   virtual void parseInstructions(DataExtractor Data, uint32_t *Offset,
43*0a6a1f1dSLionel Sambuc                                  uint32_t EndOffset);
44f4a2713aSLionel Sambuc 
45f4a2713aSLionel Sambuc   /// \brief Dump the entry header to the given output stream.
46f4a2713aSLionel Sambuc   virtual void dumpHeader(raw_ostream &OS) const = 0;
47f4a2713aSLionel Sambuc 
48f4a2713aSLionel Sambuc   /// \brief Dump the entry's instructions to the given output stream.
49f4a2713aSLionel Sambuc   virtual void dumpInstructions(raw_ostream &OS) const;
50f4a2713aSLionel Sambuc 
51f4a2713aSLionel Sambuc protected:
52f4a2713aSLionel Sambuc   const FrameKind Kind;
53f4a2713aSLionel Sambuc 
54f4a2713aSLionel Sambuc   /// \brief Offset of this entry in the section.
55f4a2713aSLionel Sambuc   uint64_t Offset;
56f4a2713aSLionel Sambuc 
57f4a2713aSLionel Sambuc   /// \brief Entry length as specified in DWARF.
58f4a2713aSLionel Sambuc   uint64_t Length;
59f4a2713aSLionel Sambuc 
60f4a2713aSLionel Sambuc   /// An entry may contain CFI instructions. An instruction consists of an
61f4a2713aSLionel Sambuc   /// opcode and an optional sequence of operands.
62f4a2713aSLionel Sambuc   typedef std::vector<uint64_t> Operands;
63f4a2713aSLionel Sambuc   struct Instruction {
Instructionllvm::FrameEntry::Instruction64f4a2713aSLionel Sambuc     Instruction(uint8_t Opcode)
65f4a2713aSLionel Sambuc       : Opcode(Opcode)
66f4a2713aSLionel Sambuc     {}
67f4a2713aSLionel Sambuc 
68f4a2713aSLionel Sambuc     uint8_t Opcode;
69f4a2713aSLionel Sambuc     Operands Ops;
70f4a2713aSLionel Sambuc   };
71f4a2713aSLionel Sambuc 
72f4a2713aSLionel Sambuc   std::vector<Instruction> Instructions;
73f4a2713aSLionel Sambuc 
74f4a2713aSLionel Sambuc   /// Convenience methods to add a new instruction with the given opcode and
75f4a2713aSLionel Sambuc   /// operands to the Instructions vector.
addInstruction(uint8_t Opcode)76f4a2713aSLionel Sambuc   void addInstruction(uint8_t Opcode) {
77f4a2713aSLionel Sambuc     Instructions.push_back(Instruction(Opcode));
78f4a2713aSLionel Sambuc   }
79f4a2713aSLionel Sambuc 
addInstruction(uint8_t Opcode,uint64_t Operand1)80f4a2713aSLionel Sambuc   void addInstruction(uint8_t Opcode, uint64_t Operand1) {
81f4a2713aSLionel Sambuc     Instructions.push_back(Instruction(Opcode));
82f4a2713aSLionel Sambuc     Instructions.back().Ops.push_back(Operand1);
83f4a2713aSLionel Sambuc   }
84f4a2713aSLionel Sambuc 
addInstruction(uint8_t Opcode,uint64_t Operand1,uint64_t Operand2)85f4a2713aSLionel Sambuc   void addInstruction(uint8_t Opcode, uint64_t Operand1, uint64_t Operand2) {
86f4a2713aSLionel Sambuc     Instructions.push_back(Instruction(Opcode));
87f4a2713aSLionel Sambuc     Instructions.back().Ops.push_back(Operand1);
88f4a2713aSLionel Sambuc     Instructions.back().Ops.push_back(Operand2);
89f4a2713aSLionel Sambuc   }
90f4a2713aSLionel Sambuc };
91f4a2713aSLionel Sambuc 
92f4a2713aSLionel Sambuc 
93f4a2713aSLionel Sambuc // See DWARF standard v3, section 7.23
94f4a2713aSLionel Sambuc const uint8_t DWARF_CFI_PRIMARY_OPCODE_MASK = 0xc0;
95f4a2713aSLionel Sambuc const uint8_t DWARF_CFI_PRIMARY_OPERAND_MASK = 0x3f;
96f4a2713aSLionel Sambuc 
parseInstructions(DataExtractor Data,uint32_t * Offset,uint32_t EndOffset)97*0a6a1f1dSLionel Sambuc void FrameEntry::parseInstructions(DataExtractor Data, uint32_t *Offset,
98*0a6a1f1dSLionel Sambuc                                    uint32_t EndOffset) {
99f4a2713aSLionel Sambuc   while (*Offset < EndOffset) {
100f4a2713aSLionel Sambuc     uint8_t Opcode = Data.getU8(Offset);
101f4a2713aSLionel Sambuc     // Some instructions have a primary opcode encoded in the top bits.
102f4a2713aSLionel Sambuc     uint8_t Primary = Opcode & DWARF_CFI_PRIMARY_OPCODE_MASK;
103f4a2713aSLionel Sambuc 
104f4a2713aSLionel Sambuc     if (Primary) {
105f4a2713aSLionel Sambuc       // If it's a primary opcode, the first operand is encoded in the bottom
106f4a2713aSLionel Sambuc       // bits of the opcode itself.
107f4a2713aSLionel Sambuc       uint64_t Op1 = Opcode & DWARF_CFI_PRIMARY_OPERAND_MASK;
108f4a2713aSLionel Sambuc       switch (Primary) {
109f4a2713aSLionel Sambuc         default: llvm_unreachable("Impossible primary CFI opcode");
110f4a2713aSLionel Sambuc         case DW_CFA_advance_loc:
111f4a2713aSLionel Sambuc         case DW_CFA_restore:
112f4a2713aSLionel Sambuc           addInstruction(Primary, Op1);
113f4a2713aSLionel Sambuc           break;
114f4a2713aSLionel Sambuc         case DW_CFA_offset:
115f4a2713aSLionel Sambuc           addInstruction(Primary, Op1, Data.getULEB128(Offset));
116f4a2713aSLionel Sambuc           break;
117f4a2713aSLionel Sambuc       }
118f4a2713aSLionel Sambuc     } else {
119f4a2713aSLionel Sambuc       // Extended opcode - its value is Opcode itself.
120f4a2713aSLionel Sambuc       switch (Opcode) {
121f4a2713aSLionel Sambuc         default: llvm_unreachable("Invalid extended CFI opcode");
122f4a2713aSLionel Sambuc         case DW_CFA_nop:
123f4a2713aSLionel Sambuc         case DW_CFA_remember_state:
124f4a2713aSLionel Sambuc         case DW_CFA_restore_state:
125*0a6a1f1dSLionel Sambuc         case DW_CFA_GNU_window_save:
126f4a2713aSLionel Sambuc           // No operands
127f4a2713aSLionel Sambuc           addInstruction(Opcode);
128f4a2713aSLionel Sambuc           break;
129f4a2713aSLionel Sambuc         case DW_CFA_set_loc:
130f4a2713aSLionel Sambuc           // Operands: Address
131f4a2713aSLionel Sambuc           addInstruction(Opcode, Data.getAddress(Offset));
132f4a2713aSLionel Sambuc           break;
133f4a2713aSLionel Sambuc         case DW_CFA_advance_loc1:
134f4a2713aSLionel Sambuc           // Operands: 1-byte delta
135f4a2713aSLionel Sambuc           addInstruction(Opcode, Data.getU8(Offset));
136f4a2713aSLionel Sambuc           break;
137f4a2713aSLionel Sambuc         case DW_CFA_advance_loc2:
138f4a2713aSLionel Sambuc           // Operands: 2-byte delta
139f4a2713aSLionel Sambuc           addInstruction(Opcode, Data.getU16(Offset));
140f4a2713aSLionel Sambuc           break;
141f4a2713aSLionel Sambuc         case DW_CFA_advance_loc4:
142f4a2713aSLionel Sambuc           // Operands: 4-byte delta
143f4a2713aSLionel Sambuc           addInstruction(Opcode, Data.getU32(Offset));
144f4a2713aSLionel Sambuc           break;
145f4a2713aSLionel Sambuc         case DW_CFA_restore_extended:
146f4a2713aSLionel Sambuc         case DW_CFA_undefined:
147f4a2713aSLionel Sambuc         case DW_CFA_same_value:
148f4a2713aSLionel Sambuc         case DW_CFA_def_cfa_register:
149f4a2713aSLionel Sambuc         case DW_CFA_def_cfa_offset:
150f4a2713aSLionel Sambuc           // Operands: ULEB128
151f4a2713aSLionel Sambuc           addInstruction(Opcode, Data.getULEB128(Offset));
152f4a2713aSLionel Sambuc           break;
153f4a2713aSLionel Sambuc         case DW_CFA_def_cfa_offset_sf:
154f4a2713aSLionel Sambuc           // Operands: SLEB128
155f4a2713aSLionel Sambuc           addInstruction(Opcode, Data.getSLEB128(Offset));
156f4a2713aSLionel Sambuc           break;
157f4a2713aSLionel Sambuc         case DW_CFA_offset_extended:
158f4a2713aSLionel Sambuc         case DW_CFA_register:
159f4a2713aSLionel Sambuc         case DW_CFA_def_cfa:
160f4a2713aSLionel Sambuc         case DW_CFA_val_offset:
161f4a2713aSLionel Sambuc           // Operands: ULEB128, ULEB128
162f4a2713aSLionel Sambuc           addInstruction(Opcode, Data.getULEB128(Offset),
163f4a2713aSLionel Sambuc                                  Data.getULEB128(Offset));
164f4a2713aSLionel Sambuc           break;
165f4a2713aSLionel Sambuc         case DW_CFA_offset_extended_sf:
166f4a2713aSLionel Sambuc         case DW_CFA_def_cfa_sf:
167f4a2713aSLionel Sambuc         case DW_CFA_val_offset_sf:
168f4a2713aSLionel Sambuc           // Operands: ULEB128, SLEB128
169f4a2713aSLionel Sambuc           addInstruction(Opcode, Data.getULEB128(Offset),
170f4a2713aSLionel Sambuc                                  Data.getSLEB128(Offset));
171f4a2713aSLionel Sambuc           break;
172f4a2713aSLionel Sambuc         case DW_CFA_def_cfa_expression:
173f4a2713aSLionel Sambuc         case DW_CFA_expression:
174f4a2713aSLionel Sambuc         case DW_CFA_val_expression:
175f4a2713aSLionel Sambuc           // TODO: implement this
176f4a2713aSLionel Sambuc           report_fatal_error("Values with expressions not implemented yet!");
177f4a2713aSLionel Sambuc       }
178f4a2713aSLionel Sambuc     }
179f4a2713aSLionel Sambuc   }
180f4a2713aSLionel Sambuc }
181f4a2713aSLionel Sambuc 
182f4a2713aSLionel Sambuc 
dumpInstructions(raw_ostream & OS) const183f4a2713aSLionel Sambuc void FrameEntry::dumpInstructions(raw_ostream &OS) const {
184f4a2713aSLionel Sambuc   // TODO: at the moment only instruction names are dumped. Expand this to
185f4a2713aSLionel Sambuc   // dump operands as well.
186*0a6a1f1dSLionel Sambuc   for (const auto &Instr : Instructions) {
187*0a6a1f1dSLionel Sambuc     uint8_t Opcode = Instr.Opcode;
188f4a2713aSLionel Sambuc     if (Opcode & DWARF_CFI_PRIMARY_OPCODE_MASK)
189f4a2713aSLionel Sambuc       Opcode &= DWARF_CFI_PRIMARY_OPCODE_MASK;
190f4a2713aSLionel Sambuc     OS << "  " << CallFrameString(Opcode) << ":\n";
191f4a2713aSLionel Sambuc   }
192f4a2713aSLionel Sambuc }
193f4a2713aSLionel Sambuc 
194f4a2713aSLionel Sambuc 
195f4a2713aSLionel Sambuc namespace {
196f4a2713aSLionel Sambuc /// \brief DWARF Common Information Entry (CIE)
197f4a2713aSLionel Sambuc class CIE : public FrameEntry {
198f4a2713aSLionel Sambuc public:
199f4a2713aSLionel Sambuc   // CIEs (and FDEs) are simply container classes, so the only sensible way to
200f4a2713aSLionel Sambuc   // create them is by providing the full parsed contents in the constructor.
CIE(uint64_t Offset,uint64_t Length,uint8_t Version,SmallString<8> Augmentation,uint64_t CodeAlignmentFactor,int64_t DataAlignmentFactor,uint64_t ReturnAddressRegister)201*0a6a1f1dSLionel Sambuc   CIE(uint64_t Offset, uint64_t Length, uint8_t Version,
202f4a2713aSLionel Sambuc       SmallString<8> Augmentation, uint64_t CodeAlignmentFactor,
203f4a2713aSLionel Sambuc       int64_t DataAlignmentFactor, uint64_t ReturnAddressRegister)
204*0a6a1f1dSLionel Sambuc       : FrameEntry(FK_CIE, Offset, Length), Version(Version),
205*0a6a1f1dSLionel Sambuc         Augmentation(std::move(Augmentation)),
206*0a6a1f1dSLionel Sambuc         CodeAlignmentFactor(CodeAlignmentFactor),
207f4a2713aSLionel Sambuc         DataAlignmentFactor(DataAlignmentFactor),
208f4a2713aSLionel Sambuc         ReturnAddressRegister(ReturnAddressRegister) {}
209f4a2713aSLionel Sambuc 
~CIE()210f4a2713aSLionel Sambuc   ~CIE() {
211f4a2713aSLionel Sambuc   }
212f4a2713aSLionel Sambuc 
dumpHeader(raw_ostream & OS) const213*0a6a1f1dSLionel Sambuc   void dumpHeader(raw_ostream &OS) const override {
214f4a2713aSLionel Sambuc     OS << format("%08x %08x %08x CIE",
215f4a2713aSLionel Sambuc                  (uint32_t)Offset, (uint32_t)Length, DW_CIE_ID)
216f4a2713aSLionel Sambuc        << "\n";
217f4a2713aSLionel Sambuc     OS << format("  Version:               %d\n", Version);
218f4a2713aSLionel Sambuc     OS << "  Augmentation:          \"" << Augmentation << "\"\n";
219f4a2713aSLionel Sambuc     OS << format("  Code alignment factor: %u\n",
220f4a2713aSLionel Sambuc                  (uint32_t)CodeAlignmentFactor);
221f4a2713aSLionel Sambuc     OS << format("  Data alignment factor: %d\n",
222f4a2713aSLionel Sambuc                  (int32_t)DataAlignmentFactor);
223f4a2713aSLionel Sambuc     OS << format("  Return address column: %d\n",
224f4a2713aSLionel Sambuc                  (int32_t)ReturnAddressRegister);
225f4a2713aSLionel Sambuc     OS << "\n";
226f4a2713aSLionel Sambuc   }
227f4a2713aSLionel Sambuc 
classof(const FrameEntry * FE)228f4a2713aSLionel Sambuc   static bool classof(const FrameEntry *FE) {
229f4a2713aSLionel Sambuc     return FE->getKind() == FK_CIE;
230f4a2713aSLionel Sambuc   }
231f4a2713aSLionel Sambuc 
232f4a2713aSLionel Sambuc private:
233f4a2713aSLionel Sambuc   /// The following fields are defined in section 6.4.1 of the DWARF standard v3
234f4a2713aSLionel Sambuc   uint8_t Version;
235f4a2713aSLionel Sambuc   SmallString<8> Augmentation;
236f4a2713aSLionel Sambuc   uint64_t CodeAlignmentFactor;
237f4a2713aSLionel Sambuc   int64_t DataAlignmentFactor;
238f4a2713aSLionel Sambuc   uint64_t ReturnAddressRegister;
239f4a2713aSLionel Sambuc };
240f4a2713aSLionel Sambuc 
241f4a2713aSLionel Sambuc 
242f4a2713aSLionel Sambuc /// \brief DWARF Frame Description Entry (FDE)
243f4a2713aSLionel Sambuc class FDE : public FrameEntry {
244f4a2713aSLionel Sambuc public:
245f4a2713aSLionel Sambuc   // Each FDE has a CIE it's "linked to". Our FDE contains is constructed with
246f4a2713aSLionel Sambuc   // an offset to the CIE (provided by parsing the FDE header). The CIE itself
247f4a2713aSLionel Sambuc   // is obtained lazily once it's actually required.
FDE(uint64_t Offset,uint64_t Length,int64_t LinkedCIEOffset,uint64_t InitialLocation,uint64_t AddressRange)248*0a6a1f1dSLionel Sambuc   FDE(uint64_t Offset, uint64_t Length, int64_t LinkedCIEOffset,
249*0a6a1f1dSLionel Sambuc       uint64_t InitialLocation, uint64_t AddressRange)
250*0a6a1f1dSLionel Sambuc       : FrameEntry(FK_FDE, Offset, Length), LinkedCIEOffset(LinkedCIEOffset),
251f4a2713aSLionel Sambuc         InitialLocation(InitialLocation), AddressRange(AddressRange),
252*0a6a1f1dSLionel Sambuc         LinkedCIE(nullptr) {}
253f4a2713aSLionel Sambuc 
~FDE()254f4a2713aSLionel Sambuc   ~FDE() {
255f4a2713aSLionel Sambuc   }
256f4a2713aSLionel Sambuc 
dumpHeader(raw_ostream & OS) const257*0a6a1f1dSLionel Sambuc   void dumpHeader(raw_ostream &OS) const override {
258f4a2713aSLionel Sambuc     OS << format("%08x %08x %08x FDE ",
259f4a2713aSLionel Sambuc                  (uint32_t)Offset, (uint32_t)Length, (int32_t)LinkedCIEOffset);
260f4a2713aSLionel Sambuc     OS << format("cie=%08x pc=%08x...%08x\n",
261f4a2713aSLionel Sambuc                  (int32_t)LinkedCIEOffset,
262f4a2713aSLionel Sambuc                  (uint32_t)InitialLocation,
263f4a2713aSLionel Sambuc                  (uint32_t)InitialLocation + (uint32_t)AddressRange);
264f4a2713aSLionel Sambuc     if (LinkedCIE) {
265f4a2713aSLionel Sambuc       OS << format("%p\n", LinkedCIE);
266f4a2713aSLionel Sambuc     }
267f4a2713aSLionel Sambuc   }
268f4a2713aSLionel Sambuc 
classof(const FrameEntry * FE)269f4a2713aSLionel Sambuc   static bool classof(const FrameEntry *FE) {
270f4a2713aSLionel Sambuc     return FE->getKind() == FK_FDE;
271f4a2713aSLionel Sambuc   }
272f4a2713aSLionel Sambuc 
273*0a6a1f1dSLionel Sambuc private:
274f4a2713aSLionel Sambuc   /// The following fields are defined in section 6.4.1 of the DWARF standard v3
275f4a2713aSLionel Sambuc   uint64_t LinkedCIEOffset;
276f4a2713aSLionel Sambuc   uint64_t InitialLocation;
277f4a2713aSLionel Sambuc   uint64_t AddressRange;
278f4a2713aSLionel Sambuc   CIE *LinkedCIE;
279f4a2713aSLionel Sambuc };
280f4a2713aSLionel Sambuc } // end anonymous namespace
281f4a2713aSLionel Sambuc 
282f4a2713aSLionel Sambuc 
DWARFDebugFrame()283f4a2713aSLionel Sambuc DWARFDebugFrame::DWARFDebugFrame() {
284f4a2713aSLionel Sambuc }
285f4a2713aSLionel Sambuc 
~DWARFDebugFrame()286f4a2713aSLionel Sambuc DWARFDebugFrame::~DWARFDebugFrame() {
287f4a2713aSLionel Sambuc }
288f4a2713aSLionel Sambuc 
dumpDataAux(DataExtractor Data,uint32_t Offset,int Length)289f4a2713aSLionel Sambuc static void LLVM_ATTRIBUTE_UNUSED dumpDataAux(DataExtractor Data,
290f4a2713aSLionel Sambuc                                               uint32_t Offset, int Length) {
291f4a2713aSLionel Sambuc   errs() << "DUMP: ";
292f4a2713aSLionel Sambuc   for (int i = 0; i < Length; ++i) {
293f4a2713aSLionel Sambuc     uint8_t c = Data.getU8(&Offset);
294f4a2713aSLionel Sambuc     errs().write_hex(c); errs() << " ";
295f4a2713aSLionel Sambuc   }
296f4a2713aSLionel Sambuc   errs() << "\n";
297f4a2713aSLionel Sambuc }
298f4a2713aSLionel Sambuc 
299f4a2713aSLionel Sambuc 
parse(DataExtractor Data)300f4a2713aSLionel Sambuc void DWARFDebugFrame::parse(DataExtractor Data) {
301f4a2713aSLionel Sambuc   uint32_t Offset = 0;
302f4a2713aSLionel Sambuc 
303f4a2713aSLionel Sambuc   while (Data.isValidOffset(Offset)) {
304f4a2713aSLionel Sambuc     uint32_t StartOffset = Offset;
305f4a2713aSLionel Sambuc 
306f4a2713aSLionel Sambuc     bool IsDWARF64 = false;
307f4a2713aSLionel Sambuc     uint64_t Length = Data.getU32(&Offset);
308f4a2713aSLionel Sambuc     uint64_t Id;
309f4a2713aSLionel Sambuc 
310f4a2713aSLionel Sambuc     if (Length == UINT32_MAX) {
311f4a2713aSLionel Sambuc       // DWARF-64 is distinguished by the first 32 bits of the initial length
312f4a2713aSLionel Sambuc       // field being 0xffffffff. Then, the next 64 bits are the actual entry
313f4a2713aSLionel Sambuc       // length.
314f4a2713aSLionel Sambuc       IsDWARF64 = true;
315f4a2713aSLionel Sambuc       Length = Data.getU64(&Offset);
316f4a2713aSLionel Sambuc     }
317f4a2713aSLionel Sambuc 
318f4a2713aSLionel Sambuc     // At this point, Offset points to the next field after Length.
319f4a2713aSLionel Sambuc     // Length is the structure size excluding itself. Compute an offset one
320f4a2713aSLionel Sambuc     // past the end of the structure (needed to know how many instructions to
321f4a2713aSLionel Sambuc     // read).
322f4a2713aSLionel Sambuc     // TODO: For honest DWARF64 support, DataExtractor will have to treat
323f4a2713aSLionel Sambuc     //       offset_ptr as uint64_t*
324f4a2713aSLionel Sambuc     uint32_t EndStructureOffset = Offset + static_cast<uint32_t>(Length);
325f4a2713aSLionel Sambuc 
326f4a2713aSLionel Sambuc     // The Id field's size depends on the DWARF format
327f4a2713aSLionel Sambuc     Id = Data.getUnsigned(&Offset, IsDWARF64 ? 8 : 4);
328f4a2713aSLionel Sambuc     bool IsCIE = ((IsDWARF64 && Id == DW64_CIE_ID) || Id == DW_CIE_ID);
329f4a2713aSLionel Sambuc 
330f4a2713aSLionel Sambuc     if (IsCIE) {
331f4a2713aSLionel Sambuc       // Note: this is specifically DWARFv3 CIE header structure. It was
332f4a2713aSLionel Sambuc       // changed in DWARFv4. We currently don't support reading DWARFv4
333f4a2713aSLionel Sambuc       // here because LLVM itself does not emit it (and LLDB doesn't
334f4a2713aSLionel Sambuc       // support it either).
335f4a2713aSLionel Sambuc       uint8_t Version = Data.getU8(&Offset);
336f4a2713aSLionel Sambuc       const char *Augmentation = Data.getCStr(&Offset);
337f4a2713aSLionel Sambuc       uint64_t CodeAlignmentFactor = Data.getULEB128(&Offset);
338f4a2713aSLionel Sambuc       int64_t DataAlignmentFactor = Data.getSLEB128(&Offset);
339f4a2713aSLionel Sambuc       uint64_t ReturnAddressRegister = Data.getULEB128(&Offset);
340f4a2713aSLionel Sambuc 
341*0a6a1f1dSLionel Sambuc       Entries.emplace_back(new CIE(StartOffset, Length, Version,
342f4a2713aSLionel Sambuc                                    StringRef(Augmentation), CodeAlignmentFactor,
343*0a6a1f1dSLionel Sambuc                                    DataAlignmentFactor, ReturnAddressRegister));
344f4a2713aSLionel Sambuc     } else {
345f4a2713aSLionel Sambuc       // FDE
346f4a2713aSLionel Sambuc       uint64_t CIEPointer = Id;
347f4a2713aSLionel Sambuc       uint64_t InitialLocation = Data.getAddress(&Offset);
348f4a2713aSLionel Sambuc       uint64_t AddressRange = Data.getAddress(&Offset);
349f4a2713aSLionel Sambuc 
350*0a6a1f1dSLionel Sambuc       Entries.emplace_back(new FDE(StartOffset, Length, CIEPointer,
351*0a6a1f1dSLionel Sambuc                                    InitialLocation, AddressRange));
352f4a2713aSLionel Sambuc     }
353f4a2713aSLionel Sambuc 
354*0a6a1f1dSLionel Sambuc     Entries.back()->parseInstructions(Data, &Offset, EndStructureOffset);
355f4a2713aSLionel Sambuc 
356*0a6a1f1dSLionel Sambuc     if (Offset != EndStructureOffset) {
357f4a2713aSLionel Sambuc       std::string Str;
358f4a2713aSLionel Sambuc       raw_string_ostream OS(Str);
359*0a6a1f1dSLionel Sambuc       OS << format("Parsing entry instructions at %lx failed", StartOffset);
360f4a2713aSLionel Sambuc       report_fatal_error(Str);
361f4a2713aSLionel Sambuc     }
362f4a2713aSLionel Sambuc   }
363f4a2713aSLionel Sambuc }
364f4a2713aSLionel Sambuc 
365f4a2713aSLionel Sambuc 
dump(raw_ostream & OS) const366f4a2713aSLionel Sambuc void DWARFDebugFrame::dump(raw_ostream &OS) const {
367f4a2713aSLionel Sambuc   OS << "\n";
368*0a6a1f1dSLionel Sambuc   for (const auto &Entry : Entries) {
369f4a2713aSLionel Sambuc     Entry->dumpHeader(OS);
370f4a2713aSLionel Sambuc     Entry->dumpInstructions(OS);
371f4a2713aSLionel Sambuc     OS << "\n";
372f4a2713aSLionel Sambuc   }
373f4a2713aSLionel Sambuc }
374f4a2713aSLionel Sambuc 
375