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