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