17a7e6055SDimitry Andric //===- DWARFDebugFrame.h - Parsing of .debug_frame ------------------------===//
2ff0cc061SDimitry Andric //
3ff0cc061SDimitry Andric //                     The LLVM Compiler Infrastructure
4ff0cc061SDimitry Andric //
5ff0cc061SDimitry Andric // This file is distributed under the University of Illinois Open Source
6ff0cc061SDimitry Andric // License. See LICENSE.TXT for details.
7ff0cc061SDimitry Andric //
8ff0cc061SDimitry Andric //===----------------------------------------------------------------------===//
9ff0cc061SDimitry Andric 
10db17bf38SDimitry Andric #include "llvm/DebugInfo/DWARF/DWARFDebugFrame.h"
11db17bf38SDimitry Andric 
12ff0cc061SDimitry Andric #include "llvm/ADT/ArrayRef.h"
13ff0cc061SDimitry Andric #include "llvm/ADT/DenseMap.h"
143ca95b02SDimitry Andric #include "llvm/ADT/Optional.h"
15d88c1a5aSDimitry Andric #include "llvm/ADT/STLExtras.h"
16db17bf38SDimitry Andric #include "llvm/ADT/SmallString.h"
173ca95b02SDimitry Andric #include "llvm/ADT/StringExtras.h"
18d88c1a5aSDimitry Andric #include "llvm/ADT/StringRef.h"
19db17bf38SDimitry Andric #include "llvm/BinaryFormat/Dwarf.h"
20ff0cc061SDimitry Andric #include "llvm/Support/Casting.h"
21d88c1a5aSDimitry Andric #include "llvm/Support/Compiler.h"
22d88c1a5aSDimitry Andric #include "llvm/Support/DataExtractor.h"
23ff0cc061SDimitry Andric #include "llvm/Support/ErrorHandling.h"
24ff0cc061SDimitry Andric #include "llvm/Support/Format.h"
25ff0cc061SDimitry Andric #include "llvm/Support/raw_ostream.h"
26d88c1a5aSDimitry Andric #include <algorithm>
27d88c1a5aSDimitry Andric #include <cassert>
28d88c1a5aSDimitry Andric #include <cinttypes>
29d88c1a5aSDimitry Andric #include <cstdint>
30ff0cc061SDimitry Andric #include <string>
31ff0cc061SDimitry Andric #include <vector>
32ff0cc061SDimitry Andric 
33ff0cc061SDimitry Andric using namespace llvm;
34ff0cc061SDimitry Andric using namespace dwarf;
35ff0cc061SDimitry Andric 
36ff0cc061SDimitry Andric /// \brief Abstract frame entry defining the common interface concrete
37ff0cc061SDimitry Andric /// entries implement.
38ff0cc061SDimitry Andric class llvm::FrameEntry {
39ff0cc061SDimitry Andric public:
40ff0cc061SDimitry Andric   enum FrameKind {FK_CIE, FK_FDE};
41d88c1a5aSDimitry Andric 
42ff0cc061SDimitry Andric   FrameEntry(FrameKind K, uint64_t Offset, uint64_t Length)
43ff0cc061SDimitry Andric       : Kind(K), Offset(Offset), Length(Length) {}
44ff0cc061SDimitry Andric 
45d88c1a5aSDimitry Andric   virtual ~FrameEntry() = default;
46ff0cc061SDimitry Andric 
47ff0cc061SDimitry Andric   FrameKind getKind() const { return Kind; }
48ff0cc061SDimitry Andric   virtual uint64_t getOffset() const { return Offset; }
49ff0cc061SDimitry Andric 
50ff0cc061SDimitry Andric   /// \brief Parse and store a sequence of CFI instructions from Data,
51ff0cc061SDimitry Andric   /// starting at *Offset and ending at EndOffset. If everything
52ff0cc061SDimitry Andric   /// goes well, *Offset should be equal to EndOffset when this method
53ff0cc061SDimitry Andric   /// returns. Otherwise, an error occurred.
54ff0cc061SDimitry Andric   virtual void parseInstructions(DataExtractor Data, uint32_t *Offset,
55ff0cc061SDimitry Andric                                  uint32_t EndOffset);
56ff0cc061SDimitry Andric 
57ff0cc061SDimitry Andric   /// \brief Dump the entry header to the given output stream.
58ff0cc061SDimitry Andric   virtual void dumpHeader(raw_ostream &OS) const = 0;
59ff0cc061SDimitry Andric 
60ff0cc061SDimitry Andric   /// \brief Dump the entry's instructions to the given output stream.
61ff0cc061SDimitry Andric   virtual void dumpInstructions(raw_ostream &OS) const;
62ff0cc061SDimitry Andric 
63ff0cc061SDimitry Andric protected:
64ff0cc061SDimitry Andric   const FrameKind Kind;
65ff0cc061SDimitry Andric 
66ff0cc061SDimitry Andric   /// \brief Offset of this entry in the section.
67ff0cc061SDimitry Andric   uint64_t Offset;
68ff0cc061SDimitry Andric 
69ff0cc061SDimitry Andric   /// \brief Entry length as specified in DWARF.
70ff0cc061SDimitry Andric   uint64_t Length;
71ff0cc061SDimitry Andric 
72ff0cc061SDimitry Andric   /// An entry may contain CFI instructions. An instruction consists of an
73ff0cc061SDimitry Andric   /// opcode and an optional sequence of operands.
74ff0cc061SDimitry Andric   typedef std::vector<uint64_t> Operands;
75ff0cc061SDimitry Andric   struct Instruction {
76ff0cc061SDimitry Andric     Instruction(uint8_t Opcode)
77ff0cc061SDimitry Andric       : Opcode(Opcode)
78ff0cc061SDimitry Andric     {}
79ff0cc061SDimitry Andric 
80ff0cc061SDimitry Andric     uint8_t Opcode;
81ff0cc061SDimitry Andric     Operands Ops;
82ff0cc061SDimitry Andric   };
83ff0cc061SDimitry Andric 
84ff0cc061SDimitry Andric   std::vector<Instruction> Instructions;
85ff0cc061SDimitry Andric 
86ff0cc061SDimitry Andric   /// Convenience methods to add a new instruction with the given opcode and
87ff0cc061SDimitry Andric   /// operands to the Instructions vector.
88ff0cc061SDimitry Andric   void addInstruction(uint8_t Opcode) {
89ff0cc061SDimitry Andric     Instructions.push_back(Instruction(Opcode));
90ff0cc061SDimitry Andric   }
91ff0cc061SDimitry Andric 
92ff0cc061SDimitry Andric   void addInstruction(uint8_t Opcode, uint64_t Operand1) {
93ff0cc061SDimitry Andric     Instructions.push_back(Instruction(Opcode));
94ff0cc061SDimitry Andric     Instructions.back().Ops.push_back(Operand1);
95ff0cc061SDimitry Andric   }
96ff0cc061SDimitry Andric 
97ff0cc061SDimitry Andric   void addInstruction(uint8_t Opcode, uint64_t Operand1, uint64_t Operand2) {
98ff0cc061SDimitry Andric     Instructions.push_back(Instruction(Opcode));
99ff0cc061SDimitry Andric     Instructions.back().Ops.push_back(Operand1);
100ff0cc061SDimitry Andric     Instructions.back().Ops.push_back(Operand2);
101ff0cc061SDimitry Andric   }
102ff0cc061SDimitry Andric };
103ff0cc061SDimitry Andric 
104ff0cc061SDimitry Andric // See DWARF standard v3, section 7.23
105ff0cc061SDimitry Andric const uint8_t DWARF_CFI_PRIMARY_OPCODE_MASK = 0xc0;
106ff0cc061SDimitry Andric const uint8_t DWARF_CFI_PRIMARY_OPERAND_MASK = 0x3f;
107ff0cc061SDimitry Andric 
108ff0cc061SDimitry Andric void FrameEntry::parseInstructions(DataExtractor Data, uint32_t *Offset,
109ff0cc061SDimitry Andric                                    uint32_t EndOffset) {
110ff0cc061SDimitry Andric   while (*Offset < EndOffset) {
111ff0cc061SDimitry Andric     uint8_t Opcode = Data.getU8(Offset);
112ff0cc061SDimitry Andric     // Some instructions have a primary opcode encoded in the top bits.
113ff0cc061SDimitry Andric     uint8_t Primary = Opcode & DWARF_CFI_PRIMARY_OPCODE_MASK;
114ff0cc061SDimitry Andric 
115ff0cc061SDimitry Andric     if (Primary) {
116ff0cc061SDimitry Andric       // If it's a primary opcode, the first operand is encoded in the bottom
117ff0cc061SDimitry Andric       // bits of the opcode itself.
118ff0cc061SDimitry Andric       uint64_t Op1 = Opcode & DWARF_CFI_PRIMARY_OPERAND_MASK;
119ff0cc061SDimitry Andric       switch (Primary) {
120ff0cc061SDimitry Andric         default: llvm_unreachable("Impossible primary CFI opcode");
121ff0cc061SDimitry Andric         case DW_CFA_advance_loc:
122ff0cc061SDimitry Andric         case DW_CFA_restore:
123ff0cc061SDimitry Andric           addInstruction(Primary, Op1);
124ff0cc061SDimitry Andric           break;
125ff0cc061SDimitry Andric         case DW_CFA_offset:
126ff0cc061SDimitry Andric           addInstruction(Primary, Op1, Data.getULEB128(Offset));
127ff0cc061SDimitry Andric           break;
128ff0cc061SDimitry Andric       }
129ff0cc061SDimitry Andric     } else {
130ff0cc061SDimitry Andric       // Extended opcode - its value is Opcode itself.
131ff0cc061SDimitry Andric       switch (Opcode) {
132ff0cc061SDimitry Andric         default: llvm_unreachable("Invalid extended CFI opcode");
133ff0cc061SDimitry Andric         case DW_CFA_nop:
134ff0cc061SDimitry Andric         case DW_CFA_remember_state:
135ff0cc061SDimitry Andric         case DW_CFA_restore_state:
136ff0cc061SDimitry Andric         case DW_CFA_GNU_window_save:
137ff0cc061SDimitry Andric           // No operands
138ff0cc061SDimitry Andric           addInstruction(Opcode);
139ff0cc061SDimitry Andric           break;
140ff0cc061SDimitry Andric         case DW_CFA_set_loc:
141ff0cc061SDimitry Andric           // Operands: Address
142ff0cc061SDimitry Andric           addInstruction(Opcode, Data.getAddress(Offset));
143ff0cc061SDimitry Andric           break;
144ff0cc061SDimitry Andric         case DW_CFA_advance_loc1:
145ff0cc061SDimitry Andric           // Operands: 1-byte delta
146ff0cc061SDimitry Andric           addInstruction(Opcode, Data.getU8(Offset));
147ff0cc061SDimitry Andric           break;
148ff0cc061SDimitry Andric         case DW_CFA_advance_loc2:
149ff0cc061SDimitry Andric           // Operands: 2-byte delta
150ff0cc061SDimitry Andric           addInstruction(Opcode, Data.getU16(Offset));
151ff0cc061SDimitry Andric           break;
152ff0cc061SDimitry Andric         case DW_CFA_advance_loc4:
153ff0cc061SDimitry Andric           // Operands: 4-byte delta
154ff0cc061SDimitry Andric           addInstruction(Opcode, Data.getU32(Offset));
155ff0cc061SDimitry Andric           break;
156ff0cc061SDimitry Andric         case DW_CFA_restore_extended:
157ff0cc061SDimitry Andric         case DW_CFA_undefined:
158ff0cc061SDimitry Andric         case DW_CFA_same_value:
159ff0cc061SDimitry Andric         case DW_CFA_def_cfa_register:
160ff0cc061SDimitry Andric         case DW_CFA_def_cfa_offset:
161ff0cc061SDimitry Andric           // Operands: ULEB128
162ff0cc061SDimitry Andric           addInstruction(Opcode, Data.getULEB128(Offset));
163ff0cc061SDimitry Andric           break;
164ff0cc061SDimitry Andric         case DW_CFA_def_cfa_offset_sf:
165ff0cc061SDimitry Andric           // Operands: SLEB128
166ff0cc061SDimitry Andric           addInstruction(Opcode, Data.getSLEB128(Offset));
167ff0cc061SDimitry Andric           break;
168ff0cc061SDimitry Andric         case DW_CFA_offset_extended:
169ff0cc061SDimitry Andric         case DW_CFA_register:
170ff0cc061SDimitry Andric         case DW_CFA_def_cfa:
1713ca95b02SDimitry Andric         case DW_CFA_val_offset: {
172ff0cc061SDimitry Andric           // Operands: ULEB128, ULEB128
1733ca95b02SDimitry Andric           // Note: We can not embed getULEB128 directly into function
1743ca95b02SDimitry Andric           // argument list. getULEB128 changes Offset and order of evaluation
1753ca95b02SDimitry Andric           // for arguments is unspecified.
1763ca95b02SDimitry Andric           auto op1 = Data.getULEB128(Offset);
1773ca95b02SDimitry Andric           auto op2 = Data.getULEB128(Offset);
1783ca95b02SDimitry Andric           addInstruction(Opcode, op1, op2);
179ff0cc061SDimitry Andric           break;
1803ca95b02SDimitry Andric         }
181ff0cc061SDimitry Andric         case DW_CFA_offset_extended_sf:
182ff0cc061SDimitry Andric         case DW_CFA_def_cfa_sf:
1833ca95b02SDimitry Andric         case DW_CFA_val_offset_sf: {
184ff0cc061SDimitry Andric           // Operands: ULEB128, SLEB128
1853ca95b02SDimitry Andric           // Note: see comment for the previous case
1863ca95b02SDimitry Andric           auto op1 = Data.getULEB128(Offset);
1873ca95b02SDimitry Andric           auto op2 = (uint64_t)Data.getSLEB128(Offset);
1883ca95b02SDimitry Andric           addInstruction(Opcode, op1, op2);
189ff0cc061SDimitry Andric           break;
1903ca95b02SDimitry Andric         }
191ff0cc061SDimitry Andric         case DW_CFA_def_cfa_expression:
192ff0cc061SDimitry Andric         case DW_CFA_expression:
193ff0cc061SDimitry Andric         case DW_CFA_val_expression:
194ff0cc061SDimitry Andric           // TODO: implement this
195ff0cc061SDimitry Andric           report_fatal_error("Values with expressions not implemented yet!");
196ff0cc061SDimitry Andric       }
197ff0cc061SDimitry Andric     }
198ff0cc061SDimitry Andric   }
199ff0cc061SDimitry Andric }
200ff0cc061SDimitry Andric 
201ff0cc061SDimitry Andric namespace {
202d88c1a5aSDimitry Andric 
203ff0cc061SDimitry Andric /// \brief DWARF Common Information Entry (CIE)
204ff0cc061SDimitry Andric class CIE : public FrameEntry {
205ff0cc061SDimitry Andric public:
206ff0cc061SDimitry Andric   // CIEs (and FDEs) are simply container classes, so the only sensible way to
207ff0cc061SDimitry Andric   // create them is by providing the full parsed contents in the constructor.
208ff0cc061SDimitry Andric   CIE(uint64_t Offset, uint64_t Length, uint8_t Version,
209ff0cc061SDimitry Andric       SmallString<8> Augmentation, uint8_t AddressSize,
210ff0cc061SDimitry Andric       uint8_t SegmentDescriptorSize, uint64_t CodeAlignmentFactor,
2113ca95b02SDimitry Andric       int64_t DataAlignmentFactor, uint64_t ReturnAddressRegister,
2123ca95b02SDimitry Andric       SmallString<8> AugmentationData, uint32_t FDEPointerEncoding,
2133ca95b02SDimitry Andric       uint32_t LSDAPointerEncoding)
214ff0cc061SDimitry Andric       : FrameEntry(FK_CIE, Offset, Length), Version(Version),
2153ca95b02SDimitry Andric         Augmentation(std::move(Augmentation)), AddressSize(AddressSize),
216ff0cc061SDimitry Andric         SegmentDescriptorSize(SegmentDescriptorSize),
217ff0cc061SDimitry Andric         CodeAlignmentFactor(CodeAlignmentFactor),
218ff0cc061SDimitry Andric         DataAlignmentFactor(DataAlignmentFactor),
2193ca95b02SDimitry Andric         ReturnAddressRegister(ReturnAddressRegister),
2203ca95b02SDimitry Andric         AugmentationData(std::move(AugmentationData)),
2213ca95b02SDimitry Andric         FDEPointerEncoding(FDEPointerEncoding),
2223ca95b02SDimitry Andric         LSDAPointerEncoding(LSDAPointerEncoding) {}
223ff0cc061SDimitry Andric 
224d88c1a5aSDimitry Andric   ~CIE() override = default;
225ff0cc061SDimitry Andric 
2263ca95b02SDimitry Andric   StringRef getAugmentationString() const { return Augmentation; }
227ff0cc061SDimitry Andric   uint64_t getCodeAlignmentFactor() const { return CodeAlignmentFactor; }
228ff0cc061SDimitry Andric   int64_t getDataAlignmentFactor() const { return DataAlignmentFactor; }
229d88c1a5aSDimitry Andric 
2303ca95b02SDimitry Andric   uint32_t getFDEPointerEncoding() const {
2313ca95b02SDimitry Andric     return FDEPointerEncoding;
2323ca95b02SDimitry Andric   }
233d88c1a5aSDimitry Andric 
2343ca95b02SDimitry Andric   uint32_t getLSDAPointerEncoding() const {
2353ca95b02SDimitry Andric     return LSDAPointerEncoding;
2363ca95b02SDimitry Andric   }
237ff0cc061SDimitry Andric 
238ff0cc061SDimitry Andric   void dumpHeader(raw_ostream &OS) const override {
239ff0cc061SDimitry Andric     OS << format("%08x %08x %08x CIE",
240ff0cc061SDimitry Andric                  (uint32_t)Offset, (uint32_t)Length, DW_CIE_ID)
241ff0cc061SDimitry Andric        << "\n";
242ff0cc061SDimitry Andric     OS << format("  Version:               %d\n", Version);
243ff0cc061SDimitry Andric     OS << "  Augmentation:          \"" << Augmentation << "\"\n";
244ff0cc061SDimitry Andric     if (Version >= 4) {
245ff0cc061SDimitry Andric       OS << format("  Address size:          %u\n",
246ff0cc061SDimitry Andric                    (uint32_t)AddressSize);
247ff0cc061SDimitry Andric       OS << format("  Segment desc size:     %u\n",
248ff0cc061SDimitry Andric                    (uint32_t)SegmentDescriptorSize);
249ff0cc061SDimitry Andric     }
250ff0cc061SDimitry Andric     OS << format("  Code alignment factor: %u\n",
251ff0cc061SDimitry Andric                  (uint32_t)CodeAlignmentFactor);
252ff0cc061SDimitry Andric     OS << format("  Data alignment factor: %d\n",
253ff0cc061SDimitry Andric                  (int32_t)DataAlignmentFactor);
254ff0cc061SDimitry Andric     OS << format("  Return address column: %d\n",
255ff0cc061SDimitry Andric                  (int32_t)ReturnAddressRegister);
2563ca95b02SDimitry Andric     if (!AugmentationData.empty()) {
2573ca95b02SDimitry Andric       OS << "  Augmentation data:    ";
2583ca95b02SDimitry Andric       for (uint8_t Byte : AugmentationData)
2593ca95b02SDimitry Andric         OS << ' ' << hexdigit(Byte >> 4) << hexdigit(Byte & 0xf);
2603ca95b02SDimitry Andric       OS << "\n";
2613ca95b02SDimitry Andric     }
262ff0cc061SDimitry Andric     OS << "\n";
263ff0cc061SDimitry Andric   }
264ff0cc061SDimitry Andric 
265ff0cc061SDimitry Andric   static bool classof(const FrameEntry *FE) {
266ff0cc061SDimitry Andric     return FE->getKind() == FK_CIE;
267ff0cc061SDimitry Andric   }
268ff0cc061SDimitry Andric 
269ff0cc061SDimitry Andric private:
270ff0cc061SDimitry Andric   /// The following fields are defined in section 6.4.1 of the DWARF standard v4
271ff0cc061SDimitry Andric   uint8_t Version;
272ff0cc061SDimitry Andric   SmallString<8> Augmentation;
273ff0cc061SDimitry Andric   uint8_t AddressSize;
274ff0cc061SDimitry Andric   uint8_t SegmentDescriptorSize;
275ff0cc061SDimitry Andric   uint64_t CodeAlignmentFactor;
276ff0cc061SDimitry Andric   int64_t DataAlignmentFactor;
277ff0cc061SDimitry Andric   uint64_t ReturnAddressRegister;
2783ca95b02SDimitry Andric 
2793ca95b02SDimitry Andric   // The following are used when the CIE represents an EH frame entry.
2803ca95b02SDimitry Andric   SmallString<8> AugmentationData;
2813ca95b02SDimitry Andric   uint32_t FDEPointerEncoding;
2823ca95b02SDimitry Andric   uint32_t LSDAPointerEncoding;
283ff0cc061SDimitry Andric };
284ff0cc061SDimitry Andric 
285ff0cc061SDimitry Andric /// \brief DWARF Frame Description Entry (FDE)
286ff0cc061SDimitry Andric class FDE : public FrameEntry {
287ff0cc061SDimitry Andric public:
288ff0cc061SDimitry Andric   // Each FDE has a CIE it's "linked to". Our FDE contains is constructed with
289ff0cc061SDimitry Andric   // an offset to the CIE (provided by parsing the FDE header). The CIE itself
290ff0cc061SDimitry Andric   // is obtained lazily once it's actually required.
291ff0cc061SDimitry Andric   FDE(uint64_t Offset, uint64_t Length, int64_t LinkedCIEOffset,
292ff0cc061SDimitry Andric       uint64_t InitialLocation, uint64_t AddressRange,
293ff0cc061SDimitry Andric       CIE *Cie)
294ff0cc061SDimitry Andric       : FrameEntry(FK_FDE, Offset, Length), LinkedCIEOffset(LinkedCIEOffset),
295ff0cc061SDimitry Andric         InitialLocation(InitialLocation), AddressRange(AddressRange),
296ff0cc061SDimitry Andric         LinkedCIE(Cie) {}
297ff0cc061SDimitry Andric 
298d88c1a5aSDimitry Andric   ~FDE() override = default;
299ff0cc061SDimitry Andric 
300ff0cc061SDimitry Andric   CIE *getLinkedCIE() const { return LinkedCIE; }
301ff0cc061SDimitry Andric 
302ff0cc061SDimitry Andric   void dumpHeader(raw_ostream &OS) const override {
303ff0cc061SDimitry Andric     OS << format("%08x %08x %08x FDE ",
304ff0cc061SDimitry Andric                  (uint32_t)Offset, (uint32_t)Length, (int32_t)LinkedCIEOffset);
305ff0cc061SDimitry Andric     OS << format("cie=%08x pc=%08x...%08x\n",
306ff0cc061SDimitry Andric                  (int32_t)LinkedCIEOffset,
307ff0cc061SDimitry Andric                  (uint32_t)InitialLocation,
308ff0cc061SDimitry Andric                  (uint32_t)InitialLocation + (uint32_t)AddressRange);
309ff0cc061SDimitry Andric   }
310ff0cc061SDimitry Andric 
311ff0cc061SDimitry Andric   static bool classof(const FrameEntry *FE) {
312ff0cc061SDimitry Andric     return FE->getKind() == FK_FDE;
313ff0cc061SDimitry Andric   }
314ff0cc061SDimitry Andric 
315ff0cc061SDimitry Andric private:
316ff0cc061SDimitry Andric   /// The following fields are defined in section 6.4.1 of the DWARF standard v3
317ff0cc061SDimitry Andric   uint64_t LinkedCIEOffset;
318ff0cc061SDimitry Andric   uint64_t InitialLocation;
319ff0cc061SDimitry Andric   uint64_t AddressRange;
320ff0cc061SDimitry Andric   CIE *LinkedCIE;
321ff0cc061SDimitry Andric };
322ff0cc061SDimitry Andric 
323ff0cc061SDimitry Andric /// \brief Types of operands to CF instructions.
324ff0cc061SDimitry Andric enum OperandType {
325ff0cc061SDimitry Andric   OT_Unset,
326ff0cc061SDimitry Andric   OT_None,
327ff0cc061SDimitry Andric   OT_Address,
328ff0cc061SDimitry Andric   OT_Offset,
329ff0cc061SDimitry Andric   OT_FactoredCodeOffset,
330ff0cc061SDimitry Andric   OT_SignedFactDataOffset,
331ff0cc061SDimitry Andric   OT_UnsignedFactDataOffset,
332ff0cc061SDimitry Andric   OT_Register,
333ff0cc061SDimitry Andric   OT_Expression
334ff0cc061SDimitry Andric };
335ff0cc061SDimitry Andric 
336ff0cc061SDimitry Andric } // end anonymous namespace
337ff0cc061SDimitry Andric 
338ff0cc061SDimitry Andric /// \brief Initialize the array describing the types of operands.
339ff0cc061SDimitry Andric static ArrayRef<OperandType[2]> getOperandTypes() {
340ff0cc061SDimitry Andric   static OperandType OpTypes[DW_CFA_restore+1][2];
341ff0cc061SDimitry Andric 
342ff0cc061SDimitry Andric #define DECLARE_OP2(OP, OPTYPE0, OPTYPE1)       \
343ff0cc061SDimitry Andric   do {                                          \
344ff0cc061SDimitry Andric     OpTypes[OP][0] = OPTYPE0;                   \
345ff0cc061SDimitry Andric     OpTypes[OP][1] = OPTYPE1;                   \
346d88c1a5aSDimitry Andric   } while (false)
347ff0cc061SDimitry Andric #define DECLARE_OP1(OP, OPTYPE0) DECLARE_OP2(OP, OPTYPE0, OT_None)
348ff0cc061SDimitry Andric #define DECLARE_OP0(OP) DECLARE_OP1(OP, OT_None)
349ff0cc061SDimitry Andric 
350ff0cc061SDimitry Andric   DECLARE_OP1(DW_CFA_set_loc, OT_Address);
351ff0cc061SDimitry Andric   DECLARE_OP1(DW_CFA_advance_loc, OT_FactoredCodeOffset);
352ff0cc061SDimitry Andric   DECLARE_OP1(DW_CFA_advance_loc1, OT_FactoredCodeOffset);
353ff0cc061SDimitry Andric   DECLARE_OP1(DW_CFA_advance_loc2, OT_FactoredCodeOffset);
354ff0cc061SDimitry Andric   DECLARE_OP1(DW_CFA_advance_loc4, OT_FactoredCodeOffset);
355ff0cc061SDimitry Andric   DECLARE_OP1(DW_CFA_MIPS_advance_loc8, OT_FactoredCodeOffset);
356ff0cc061SDimitry Andric   DECLARE_OP2(DW_CFA_def_cfa, OT_Register, OT_Offset);
357ff0cc061SDimitry Andric   DECLARE_OP2(DW_CFA_def_cfa_sf, OT_Register, OT_SignedFactDataOffset);
358ff0cc061SDimitry Andric   DECLARE_OP1(DW_CFA_def_cfa_register, OT_Register);
359ff0cc061SDimitry Andric   DECLARE_OP1(DW_CFA_def_cfa_offset, OT_Offset);
360ff0cc061SDimitry Andric   DECLARE_OP1(DW_CFA_def_cfa_offset_sf, OT_SignedFactDataOffset);
361ff0cc061SDimitry Andric   DECLARE_OP1(DW_CFA_def_cfa_expression, OT_Expression);
362ff0cc061SDimitry Andric   DECLARE_OP1(DW_CFA_undefined, OT_Register);
363ff0cc061SDimitry Andric   DECLARE_OP1(DW_CFA_same_value, OT_Register);
364ff0cc061SDimitry Andric   DECLARE_OP2(DW_CFA_offset, OT_Register, OT_UnsignedFactDataOffset);
365ff0cc061SDimitry Andric   DECLARE_OP2(DW_CFA_offset_extended, OT_Register, OT_UnsignedFactDataOffset);
366ff0cc061SDimitry Andric   DECLARE_OP2(DW_CFA_offset_extended_sf, OT_Register, OT_SignedFactDataOffset);
367ff0cc061SDimitry Andric   DECLARE_OP2(DW_CFA_val_offset, OT_Register, OT_UnsignedFactDataOffset);
368ff0cc061SDimitry Andric   DECLARE_OP2(DW_CFA_val_offset_sf, OT_Register, OT_SignedFactDataOffset);
369ff0cc061SDimitry Andric   DECLARE_OP2(DW_CFA_register, OT_Register, OT_Register);
370ff0cc061SDimitry Andric   DECLARE_OP2(DW_CFA_expression, OT_Register, OT_Expression);
371ff0cc061SDimitry Andric   DECLARE_OP2(DW_CFA_val_expression, OT_Register, OT_Expression);
372ff0cc061SDimitry Andric   DECLARE_OP1(DW_CFA_restore, OT_Register);
373ff0cc061SDimitry Andric   DECLARE_OP1(DW_CFA_restore_extended, OT_Register);
374ff0cc061SDimitry Andric   DECLARE_OP0(DW_CFA_remember_state);
375ff0cc061SDimitry Andric   DECLARE_OP0(DW_CFA_restore_state);
376ff0cc061SDimitry Andric   DECLARE_OP0(DW_CFA_GNU_window_save);
377ff0cc061SDimitry Andric   DECLARE_OP1(DW_CFA_GNU_args_size, OT_Offset);
378ff0cc061SDimitry Andric   DECLARE_OP0(DW_CFA_nop);
379ff0cc061SDimitry Andric 
380ff0cc061SDimitry Andric #undef DECLARE_OP0
381ff0cc061SDimitry Andric #undef DECLARE_OP1
382ff0cc061SDimitry Andric #undef DECLARE_OP2
383d88c1a5aSDimitry Andric 
384ff0cc061SDimitry Andric   return ArrayRef<OperandType[2]>(&OpTypes[0], DW_CFA_restore+1);
385ff0cc061SDimitry Andric }
386ff0cc061SDimitry Andric 
387ff0cc061SDimitry Andric static ArrayRef<OperandType[2]> OpTypes = getOperandTypes();
388ff0cc061SDimitry Andric 
389ff0cc061SDimitry Andric /// \brief Print \p Opcode's operand number \p OperandIdx which has
390ff0cc061SDimitry Andric /// value \p Operand.
391ff0cc061SDimitry Andric static void printOperand(raw_ostream &OS, uint8_t Opcode, unsigned OperandIdx,
392ff0cc061SDimitry Andric                          uint64_t Operand, uint64_t CodeAlignmentFactor,
393ff0cc061SDimitry Andric                          int64_t DataAlignmentFactor) {
394ff0cc061SDimitry Andric   assert(OperandIdx < 2);
395ff0cc061SDimitry Andric   OperandType Type = OpTypes[Opcode][OperandIdx];
396ff0cc061SDimitry Andric 
397ff0cc061SDimitry Andric   switch (Type) {
398d88c1a5aSDimitry Andric   case OT_Unset: {
399ff0cc061SDimitry Andric     OS << " Unsupported " << (OperandIdx ? "second" : "first") << " operand to";
400d88c1a5aSDimitry Andric     auto OpcodeName = CallFrameString(Opcode);
401d88c1a5aSDimitry Andric     if (!OpcodeName.empty())
402ff0cc061SDimitry Andric       OS << " " << OpcodeName;
403ff0cc061SDimitry Andric     else
404ff0cc061SDimitry Andric       OS << format(" Opcode %x",  Opcode);
405ff0cc061SDimitry Andric     break;
406d88c1a5aSDimitry Andric   }
407ff0cc061SDimitry Andric   case OT_None:
408ff0cc061SDimitry Andric     break;
409ff0cc061SDimitry Andric   case OT_Address:
410ff0cc061SDimitry Andric     OS << format(" %" PRIx64, Operand);
411ff0cc061SDimitry Andric     break;
412ff0cc061SDimitry Andric   case OT_Offset:
413ff0cc061SDimitry Andric     // The offsets are all encoded in a unsigned form, but in practice
414ff0cc061SDimitry Andric     // consumers use them signed. It's most certainly legacy due to
415ff0cc061SDimitry Andric     // the lack of signed variants in the first Dwarf standards.
416ff0cc061SDimitry Andric     OS << format(" %+" PRId64, int64_t(Operand));
417ff0cc061SDimitry Andric     break;
418ff0cc061SDimitry Andric   case OT_FactoredCodeOffset: // Always Unsigned
419ff0cc061SDimitry Andric     if (CodeAlignmentFactor)
420ff0cc061SDimitry Andric       OS << format(" %" PRId64, Operand * CodeAlignmentFactor);
421ff0cc061SDimitry Andric     else
422ff0cc061SDimitry Andric       OS << format(" %" PRId64 "*code_alignment_factor" , Operand);
423ff0cc061SDimitry Andric     break;
424ff0cc061SDimitry Andric   case OT_SignedFactDataOffset:
425ff0cc061SDimitry Andric     if (DataAlignmentFactor)
426ff0cc061SDimitry Andric       OS << format(" %" PRId64, int64_t(Operand) * DataAlignmentFactor);
427ff0cc061SDimitry Andric     else
428ff0cc061SDimitry Andric       OS << format(" %" PRId64 "*data_alignment_factor" , int64_t(Operand));
429ff0cc061SDimitry Andric     break;
430ff0cc061SDimitry Andric   case OT_UnsignedFactDataOffset:
431ff0cc061SDimitry Andric     if (DataAlignmentFactor)
432ff0cc061SDimitry Andric       OS << format(" %" PRId64, Operand * DataAlignmentFactor);
433ff0cc061SDimitry Andric     else
434ff0cc061SDimitry Andric       OS << format(" %" PRId64 "*data_alignment_factor" , Operand);
435ff0cc061SDimitry Andric     break;
436ff0cc061SDimitry Andric   case OT_Register:
437ff0cc061SDimitry Andric     OS << format(" reg%" PRId64, Operand);
438ff0cc061SDimitry Andric     break;
439ff0cc061SDimitry Andric   case OT_Expression:
440ff0cc061SDimitry Andric     OS << " expression";
441ff0cc061SDimitry Andric     break;
442ff0cc061SDimitry Andric   }
443ff0cc061SDimitry Andric }
444ff0cc061SDimitry Andric 
445ff0cc061SDimitry Andric void FrameEntry::dumpInstructions(raw_ostream &OS) const {
446ff0cc061SDimitry Andric   uint64_t CodeAlignmentFactor = 0;
447ff0cc061SDimitry Andric   int64_t DataAlignmentFactor = 0;
448ff0cc061SDimitry Andric   const CIE *Cie = dyn_cast<CIE>(this);
449ff0cc061SDimitry Andric 
450ff0cc061SDimitry Andric   if (!Cie)
451ff0cc061SDimitry Andric     Cie = cast<FDE>(this)->getLinkedCIE();
452ff0cc061SDimitry Andric   if (Cie) {
453ff0cc061SDimitry Andric     CodeAlignmentFactor = Cie->getCodeAlignmentFactor();
454ff0cc061SDimitry Andric     DataAlignmentFactor = Cie->getDataAlignmentFactor();
455ff0cc061SDimitry Andric   }
456ff0cc061SDimitry Andric 
457ff0cc061SDimitry Andric   for (const auto &Instr : Instructions) {
458ff0cc061SDimitry Andric     uint8_t Opcode = Instr.Opcode;
459ff0cc061SDimitry Andric     if (Opcode & DWARF_CFI_PRIMARY_OPCODE_MASK)
460ff0cc061SDimitry Andric       Opcode &= DWARF_CFI_PRIMARY_OPCODE_MASK;
461ff0cc061SDimitry Andric     OS << "  " << CallFrameString(Opcode) << ":";
462ff0cc061SDimitry Andric     for (unsigned i = 0; i < Instr.Ops.size(); ++i)
463ff0cc061SDimitry Andric       printOperand(OS, Opcode, i, Instr.Ops[i], CodeAlignmentFactor,
464ff0cc061SDimitry Andric                    DataAlignmentFactor);
465ff0cc061SDimitry Andric     OS << '\n';
466ff0cc061SDimitry Andric   }
467ff0cc061SDimitry Andric }
468ff0cc061SDimitry Andric 
4697a7e6055SDimitry Andric DWARFDebugFrame::DWARFDebugFrame(bool IsEH) : IsEH(IsEH) {}
470ff0cc061SDimitry Andric 
471d88c1a5aSDimitry Andric DWARFDebugFrame::~DWARFDebugFrame() = default;
472ff0cc061SDimitry Andric 
473ff0cc061SDimitry Andric static void LLVM_ATTRIBUTE_UNUSED dumpDataAux(DataExtractor Data,
474ff0cc061SDimitry Andric                                               uint32_t Offset, int Length) {
475ff0cc061SDimitry Andric   errs() << "DUMP: ";
476ff0cc061SDimitry Andric   for (int i = 0; i < Length; ++i) {
477ff0cc061SDimitry Andric     uint8_t c = Data.getU8(&Offset);
478ff0cc061SDimitry Andric     errs().write_hex(c); errs() << " ";
479ff0cc061SDimitry Andric   }
480ff0cc061SDimitry Andric   errs() << "\n";
481ff0cc061SDimitry Andric }
482ff0cc061SDimitry Andric 
4833ca95b02SDimitry Andric static unsigned getSizeForEncoding(const DataExtractor &Data,
4843ca95b02SDimitry Andric                                    unsigned symbolEncoding) {
4853ca95b02SDimitry Andric   unsigned format = symbolEncoding & 0x0f;
4863ca95b02SDimitry Andric   switch (format) {
4873ca95b02SDimitry Andric     default: llvm_unreachable("Unknown Encoding");
4887a7e6055SDimitry Andric     case DW_EH_PE_absptr:
4897a7e6055SDimitry Andric     case DW_EH_PE_signed:
4903ca95b02SDimitry Andric       return Data.getAddressSize();
4917a7e6055SDimitry Andric     case DW_EH_PE_udata2:
4927a7e6055SDimitry Andric     case DW_EH_PE_sdata2:
4933ca95b02SDimitry Andric       return 2;
4947a7e6055SDimitry Andric     case DW_EH_PE_udata4:
4957a7e6055SDimitry Andric     case DW_EH_PE_sdata4:
4963ca95b02SDimitry Andric       return 4;
4977a7e6055SDimitry Andric     case DW_EH_PE_udata8:
4987a7e6055SDimitry Andric     case DW_EH_PE_sdata8:
4993ca95b02SDimitry Andric       return 8;
5003ca95b02SDimitry Andric   }
5013ca95b02SDimitry Andric }
5023ca95b02SDimitry Andric 
5033ca95b02SDimitry Andric static uint64_t readPointer(const DataExtractor &Data, uint32_t &Offset,
5043ca95b02SDimitry Andric                             unsigned Encoding) {
5053ca95b02SDimitry Andric   switch (getSizeForEncoding(Data, Encoding)) {
5063ca95b02SDimitry Andric     case 2:
5073ca95b02SDimitry Andric       return Data.getU16(&Offset);
5083ca95b02SDimitry Andric     case 4:
5093ca95b02SDimitry Andric       return Data.getU32(&Offset);
5103ca95b02SDimitry Andric     case 8:
5113ca95b02SDimitry Andric       return Data.getU64(&Offset);
5123ca95b02SDimitry Andric     default:
5133ca95b02SDimitry Andric       llvm_unreachable("Illegal data size");
5143ca95b02SDimitry Andric   }
5153ca95b02SDimitry Andric }
516ff0cc061SDimitry Andric 
51724d58133SDimitry Andric // This is a workaround for old compilers which do not allow
51824d58133SDimitry Andric // noreturn attribute usage in lambdas. Once the support for those
51924d58133SDimitry Andric // compilers are phased out, we can remove this and return back to
52024d58133SDimitry Andric // a ReportError lambda: [StartOffset](const char *ErrorMsg).
52124d58133SDimitry Andric #define ReportError(ErrorMsg) ReportErrorImpl(StartOffset,ErrorMsg)
52224d58133SDimitry Andric static void LLVM_ATTRIBUTE_NORETURN
52324d58133SDimitry Andric ReportErrorImpl(uint32_t StartOffset, const char *ErrorMsg) {
52424d58133SDimitry Andric       std::string Str;
52524d58133SDimitry Andric       raw_string_ostream OS(Str);
52624d58133SDimitry Andric       OS << format(ErrorMsg, StartOffset);
52724d58133SDimitry Andric       OS.flush();
52824d58133SDimitry Andric       report_fatal_error(Str);
52924d58133SDimitry Andric }
53024d58133SDimitry Andric 
531ff0cc061SDimitry Andric void DWARFDebugFrame::parse(DataExtractor Data) {
532ff0cc061SDimitry Andric   uint32_t Offset = 0;
533ff0cc061SDimitry Andric   DenseMap<uint32_t, CIE *> CIEs;
534ff0cc061SDimitry Andric 
535ff0cc061SDimitry Andric   while (Data.isValidOffset(Offset)) {
536ff0cc061SDimitry Andric     uint32_t StartOffset = Offset;
537ff0cc061SDimitry Andric 
538ff0cc061SDimitry Andric     bool IsDWARF64 = false;
539ff0cc061SDimitry Andric     uint64_t Length = Data.getU32(&Offset);
540ff0cc061SDimitry Andric     uint64_t Id;
541ff0cc061SDimitry Andric 
542ff0cc061SDimitry Andric     if (Length == UINT32_MAX) {
543ff0cc061SDimitry Andric       // DWARF-64 is distinguished by the first 32 bits of the initial length
544ff0cc061SDimitry Andric       // field being 0xffffffff. Then, the next 64 bits are the actual entry
545ff0cc061SDimitry Andric       // length.
546ff0cc061SDimitry Andric       IsDWARF64 = true;
547ff0cc061SDimitry Andric       Length = Data.getU64(&Offset);
548ff0cc061SDimitry Andric     }
549ff0cc061SDimitry Andric 
550ff0cc061SDimitry Andric     // At this point, Offset points to the next field after Length.
551ff0cc061SDimitry Andric     // Length is the structure size excluding itself. Compute an offset one
552ff0cc061SDimitry Andric     // past the end of the structure (needed to know how many instructions to
553ff0cc061SDimitry Andric     // read).
554ff0cc061SDimitry Andric     // TODO: For honest DWARF64 support, DataExtractor will have to treat
555ff0cc061SDimitry Andric     //       offset_ptr as uint64_t*
5563ca95b02SDimitry Andric     uint32_t StartStructureOffset = Offset;
557ff0cc061SDimitry Andric     uint32_t EndStructureOffset = Offset + static_cast<uint32_t>(Length);
558ff0cc061SDimitry Andric 
559ff0cc061SDimitry Andric     // The Id field's size depends on the DWARF format
5603ca95b02SDimitry Andric     Id = Data.getUnsigned(&Offset, (IsDWARF64 && !IsEH) ? 8 : 4);
5613ca95b02SDimitry Andric     bool IsCIE = ((IsDWARF64 && Id == DW64_CIE_ID) ||
5623ca95b02SDimitry Andric                   Id == DW_CIE_ID ||
5633ca95b02SDimitry Andric                   (IsEH && !Id));
564ff0cc061SDimitry Andric 
565ff0cc061SDimitry Andric     if (IsCIE) {
566ff0cc061SDimitry Andric       uint8_t Version = Data.getU8(&Offset);
567ff0cc061SDimitry Andric       const char *Augmentation = Data.getCStr(&Offset);
5683ca95b02SDimitry Andric       StringRef AugmentationString(Augmentation ? Augmentation : "");
5693ca95b02SDimitry Andric       uint8_t AddressSize = Version < 4 ? Data.getAddressSize() :
5703ca95b02SDimitry Andric                                           Data.getU8(&Offset);
571ff0cc061SDimitry Andric       Data.setAddressSize(AddressSize);
572ff0cc061SDimitry Andric       uint8_t SegmentDescriptorSize = Version < 4 ? 0 : Data.getU8(&Offset);
573ff0cc061SDimitry Andric       uint64_t CodeAlignmentFactor = Data.getULEB128(&Offset);
574ff0cc061SDimitry Andric       int64_t DataAlignmentFactor = Data.getSLEB128(&Offset);
575ff0cc061SDimitry Andric       uint64_t ReturnAddressRegister = Data.getULEB128(&Offset);
576ff0cc061SDimitry Andric 
5773ca95b02SDimitry Andric       // Parse the augmentation data for EH CIEs
5783ca95b02SDimitry Andric       StringRef AugmentationData("");
5793ca95b02SDimitry Andric       uint32_t FDEPointerEncoding = DW_EH_PE_omit;
5803ca95b02SDimitry Andric       uint32_t LSDAPointerEncoding = DW_EH_PE_omit;
5813ca95b02SDimitry Andric       if (IsEH) {
5823ca95b02SDimitry Andric         Optional<uint32_t> PersonalityEncoding;
5833ca95b02SDimitry Andric         Optional<uint64_t> Personality;
5843ca95b02SDimitry Andric 
5853ca95b02SDimitry Andric         Optional<uint64_t> AugmentationLength;
5863ca95b02SDimitry Andric         uint32_t StartAugmentationOffset;
5873ca95b02SDimitry Andric         uint32_t EndAugmentationOffset;
5883ca95b02SDimitry Andric 
5893ca95b02SDimitry Andric         // Walk the augmentation string to get all the augmentation data.
5903ca95b02SDimitry Andric         for (unsigned i = 0, e = AugmentationString.size(); i != e; ++i) {
5913ca95b02SDimitry Andric           switch (AugmentationString[i]) {
5923ca95b02SDimitry Andric             default:
5933ca95b02SDimitry Andric               ReportError("Unknown augmentation character in entry at %lx");
5943ca95b02SDimitry Andric             case 'L':
5953ca95b02SDimitry Andric               LSDAPointerEncoding = Data.getU8(&Offset);
5963ca95b02SDimitry Andric               break;
5973ca95b02SDimitry Andric             case 'P': {
5983ca95b02SDimitry Andric               if (Personality)
5993ca95b02SDimitry Andric                 ReportError("Duplicate personality in entry at %lx");
6003ca95b02SDimitry Andric               PersonalityEncoding = Data.getU8(&Offset);
6013ca95b02SDimitry Andric               Personality = readPointer(Data, Offset, *PersonalityEncoding);
6023ca95b02SDimitry Andric               break;
6033ca95b02SDimitry Andric             }
6043ca95b02SDimitry Andric             case 'R':
6053ca95b02SDimitry Andric               FDEPointerEncoding = Data.getU8(&Offset);
6063ca95b02SDimitry Andric               break;
6073ca95b02SDimitry Andric             case 'z':
6083ca95b02SDimitry Andric               if (i)
6093ca95b02SDimitry Andric                 ReportError("'z' must be the first character at %lx");
6103ca95b02SDimitry Andric               // Parse the augmentation length first.  We only parse it if
6113ca95b02SDimitry Andric               // the string contains a 'z'.
6123ca95b02SDimitry Andric               AugmentationLength = Data.getULEB128(&Offset);
6133ca95b02SDimitry Andric               StartAugmentationOffset = Offset;
6143ca95b02SDimitry Andric               EndAugmentationOffset = Offset +
6153ca95b02SDimitry Andric                 static_cast<uint32_t>(*AugmentationLength);
6163ca95b02SDimitry Andric           }
6173ca95b02SDimitry Andric         }
6183ca95b02SDimitry Andric 
6193ca95b02SDimitry Andric         if (AugmentationLength.hasValue()) {
6203ca95b02SDimitry Andric           if (Offset != EndAugmentationOffset)
6213ca95b02SDimitry Andric             ReportError("Parsing augmentation data at %lx failed");
6223ca95b02SDimitry Andric 
6233ca95b02SDimitry Andric           AugmentationData = Data.getData().slice(StartAugmentationOffset,
6243ca95b02SDimitry Andric                                                   EndAugmentationOffset);
6253ca95b02SDimitry Andric         }
6263ca95b02SDimitry Andric       }
6273ca95b02SDimitry Andric 
628d88c1a5aSDimitry Andric       auto Cie = llvm::make_unique<CIE>(StartOffset, Length, Version,
6293ca95b02SDimitry Andric                                         AugmentationString, AddressSize,
630d88c1a5aSDimitry Andric                                         SegmentDescriptorSize,
631d88c1a5aSDimitry Andric                                         CodeAlignmentFactor,
632d88c1a5aSDimitry Andric                                         DataAlignmentFactor,
633d88c1a5aSDimitry Andric                                         ReturnAddressRegister,
6343ca95b02SDimitry Andric                                         AugmentationData, FDEPointerEncoding,
6353ca95b02SDimitry Andric                                         LSDAPointerEncoding);
636ff0cc061SDimitry Andric       CIEs[StartOffset] = Cie.get();
637ff0cc061SDimitry Andric       Entries.emplace_back(std::move(Cie));
638ff0cc061SDimitry Andric     } else {
639ff0cc061SDimitry Andric       // FDE
640ff0cc061SDimitry Andric       uint64_t CIEPointer = Id;
6413ca95b02SDimitry Andric       uint64_t InitialLocation = 0;
6423ca95b02SDimitry Andric       uint64_t AddressRange = 0;
6433ca95b02SDimitry Andric       CIE *Cie = CIEs[IsEH ? (StartStructureOffset - CIEPointer) : CIEPointer];
6443ca95b02SDimitry Andric 
6453ca95b02SDimitry Andric       if (IsEH) {
6463ca95b02SDimitry Andric         // The address size is encoded in the CIE we reference.
6473ca95b02SDimitry Andric         if (!Cie)
6483ca95b02SDimitry Andric           ReportError("Parsing FDE data at %lx failed due to missing CIE");
6493ca95b02SDimitry Andric 
6503ca95b02SDimitry Andric         InitialLocation = readPointer(Data, Offset,
6513ca95b02SDimitry Andric                                       Cie->getFDEPointerEncoding());
6523ca95b02SDimitry Andric         AddressRange = readPointer(Data, Offset,
6533ca95b02SDimitry Andric                                    Cie->getFDEPointerEncoding());
6543ca95b02SDimitry Andric 
6553ca95b02SDimitry Andric         StringRef AugmentationString = Cie->getAugmentationString();
6563ca95b02SDimitry Andric         if (!AugmentationString.empty()) {
6573ca95b02SDimitry Andric           // Parse the augmentation length and data for this FDE.
6583ca95b02SDimitry Andric           uint64_t AugmentationLength = Data.getULEB128(&Offset);
6593ca95b02SDimitry Andric 
6603ca95b02SDimitry Andric           uint32_t EndAugmentationOffset =
6613ca95b02SDimitry Andric             Offset + static_cast<uint32_t>(AugmentationLength);
6623ca95b02SDimitry Andric 
6633ca95b02SDimitry Andric           // Decode the LSDA if the CIE augmentation string said we should.
6643ca95b02SDimitry Andric           if (Cie->getLSDAPointerEncoding() != DW_EH_PE_omit)
6653ca95b02SDimitry Andric             readPointer(Data, Offset, Cie->getLSDAPointerEncoding());
6663ca95b02SDimitry Andric 
6673ca95b02SDimitry Andric           if (Offset != EndAugmentationOffset)
6683ca95b02SDimitry Andric             ReportError("Parsing augmentation data at %lx failed");
6693ca95b02SDimitry Andric         }
6703ca95b02SDimitry Andric       } else {
6713ca95b02SDimitry Andric         InitialLocation = Data.getAddress(&Offset);
6723ca95b02SDimitry Andric         AddressRange = Data.getAddress(&Offset);
6733ca95b02SDimitry Andric       }
674ff0cc061SDimitry Andric 
675ff0cc061SDimitry Andric       Entries.emplace_back(new FDE(StartOffset, Length, CIEPointer,
676ff0cc061SDimitry Andric                                    InitialLocation, AddressRange,
6773ca95b02SDimitry Andric                                    Cie));
678ff0cc061SDimitry Andric     }
679ff0cc061SDimitry Andric 
680ff0cc061SDimitry Andric     Entries.back()->parseInstructions(Data, &Offset, EndStructureOffset);
681ff0cc061SDimitry Andric 
6823ca95b02SDimitry Andric     if (Offset != EndStructureOffset)
6833ca95b02SDimitry Andric       ReportError("Parsing entry instructions at %lx failed");
684ff0cc061SDimitry Andric   }
685ff0cc061SDimitry Andric }
686ff0cc061SDimitry Andric 
687ff0cc061SDimitry Andric void DWARFDebugFrame::dump(raw_ostream &OS) const {
688ff0cc061SDimitry Andric   OS << "\n";
689ff0cc061SDimitry Andric   for (const auto &Entry : Entries) {
690ff0cc061SDimitry Andric     Entry->dumpHeader(OS);
691ff0cc061SDimitry Andric     Entry->dumpInstructions(OS);
692ff0cc061SDimitry Andric     OS << "\n";
693ff0cc061SDimitry Andric   }
694ff0cc061SDimitry Andric }
695