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"
14db17bf38SDimitry Andric #include "llvm/ADT/SmallString.h"
153ca95b02SDimitry Andric #include "llvm/ADT/StringExtras.h"
16d88c1a5aSDimitry Andric #include "llvm/ADT/StringRef.h"
17db17bf38SDimitry Andric #include "llvm/BinaryFormat/Dwarf.h"
18ff0cc061SDimitry Andric #include "llvm/Support/Casting.h"
19d88c1a5aSDimitry Andric #include "llvm/Support/Compiler.h"
20d88c1a5aSDimitry Andric #include "llvm/Support/DataExtractor.h"
21ff0cc061SDimitry Andric #include "llvm/Support/ErrorHandling.h"
22ff0cc061SDimitry Andric #include "llvm/Support/Format.h"
23ff0cc061SDimitry Andric #include "llvm/Support/raw_ostream.h"
24d88c1a5aSDimitry Andric #include <algorithm>
25d88c1a5aSDimitry Andric #include <cassert>
26d88c1a5aSDimitry Andric #include <cinttypes>
27d88c1a5aSDimitry Andric #include <cstdint>
28ff0cc061SDimitry Andric #include <string>
29ff0cc061SDimitry Andric #include <vector>
30ff0cc061SDimitry Andric 
31ff0cc061SDimitry Andric using namespace llvm;
32ff0cc061SDimitry Andric using namespace dwarf;
33ff0cc061SDimitry Andric 
34ff0cc061SDimitry Andric /// \brief Abstract frame entry defining the common interface concrete
35ff0cc061SDimitry Andric /// entries implement.
36ff0cc061SDimitry Andric class llvm::FrameEntry {
37ff0cc061SDimitry Andric public:
38ff0cc061SDimitry Andric   enum FrameKind {FK_CIE, FK_FDE};
39d88c1a5aSDimitry Andric 
40ff0cc061SDimitry Andric   FrameEntry(FrameKind K, uint64_t Offset, uint64_t Length)
41ff0cc061SDimitry Andric       : Kind(K), Offset(Offset), Length(Length) {}
42ff0cc061SDimitry Andric 
43d88c1a5aSDimitry Andric   virtual ~FrameEntry() = default;
44ff0cc061SDimitry Andric 
45ff0cc061SDimitry Andric   FrameKind getKind() const { return Kind; }
46ff0cc061SDimitry Andric   virtual uint64_t getOffset() const { return Offset; }
47ff0cc061SDimitry Andric 
482cab237bSDimitry Andric   /// Parse and store a sequence of CFI instructions from Data,
49ff0cc061SDimitry Andric   /// starting at *Offset and ending at EndOffset. If everything
50ff0cc061SDimitry Andric   /// goes well, *Offset should be equal to EndOffset when this method
51ff0cc061SDimitry Andric   /// returns. Otherwise, an error occurred.
52ff0cc061SDimitry Andric   virtual void parseInstructions(DataExtractor Data, uint32_t *Offset,
53ff0cc061SDimitry Andric                                  uint32_t EndOffset);
54ff0cc061SDimitry Andric 
552cab237bSDimitry Andric   /// Dump the entry header to the given output stream.
56ff0cc061SDimitry Andric   virtual void dumpHeader(raw_ostream &OS) const = 0;
57ff0cc061SDimitry Andric 
582cab237bSDimitry Andric   /// Dump the entry's instructions to the given output stream.
59ff0cc061SDimitry Andric   virtual void dumpInstructions(raw_ostream &OS) const;
60ff0cc061SDimitry Andric 
612cab237bSDimitry Andric   /// Dump the entire entry to the given output stream.
622cab237bSDimitry Andric   void dump(raw_ostream &OS) const {
632cab237bSDimitry Andric     dumpHeader(OS);
642cab237bSDimitry Andric     dumpInstructions(OS);
652cab237bSDimitry Andric     OS << "\n";
662cab237bSDimitry Andric   }
672cab237bSDimitry Andric 
68ff0cc061SDimitry Andric protected:
69ff0cc061SDimitry Andric   const FrameKind Kind;
70ff0cc061SDimitry Andric 
71ff0cc061SDimitry Andric   /// \brief Offset of this entry in the section.
72ff0cc061SDimitry Andric   uint64_t Offset;
73ff0cc061SDimitry Andric 
74ff0cc061SDimitry Andric   /// \brief Entry length as specified in DWARF.
75ff0cc061SDimitry Andric   uint64_t Length;
76ff0cc061SDimitry Andric 
77ff0cc061SDimitry Andric   /// An entry may contain CFI instructions. An instruction consists of an
78ff0cc061SDimitry Andric   /// opcode and an optional sequence of operands.
79edd7eaddSDimitry Andric   using Operands = std::vector<uint64_t>;
80ff0cc061SDimitry Andric   struct Instruction {
81ff0cc061SDimitry Andric     Instruction(uint8_t Opcode)
82ff0cc061SDimitry Andric       : Opcode(Opcode)
83ff0cc061SDimitry Andric     {}
84ff0cc061SDimitry Andric 
85ff0cc061SDimitry Andric     uint8_t Opcode;
86ff0cc061SDimitry Andric     Operands Ops;
87ff0cc061SDimitry Andric   };
88ff0cc061SDimitry Andric 
89ff0cc061SDimitry Andric   std::vector<Instruction> Instructions;
90ff0cc061SDimitry Andric 
91ff0cc061SDimitry Andric   /// Convenience methods to add a new instruction with the given opcode and
92ff0cc061SDimitry Andric   /// operands to the Instructions vector.
93ff0cc061SDimitry Andric   void addInstruction(uint8_t Opcode) {
94ff0cc061SDimitry Andric     Instructions.push_back(Instruction(Opcode));
95ff0cc061SDimitry Andric   }
96ff0cc061SDimitry Andric 
97ff0cc061SDimitry Andric   void addInstruction(uint8_t Opcode, uint64_t Operand1) {
98ff0cc061SDimitry Andric     Instructions.push_back(Instruction(Opcode));
99ff0cc061SDimitry Andric     Instructions.back().Ops.push_back(Operand1);
100ff0cc061SDimitry Andric   }
101ff0cc061SDimitry Andric 
102ff0cc061SDimitry Andric   void addInstruction(uint8_t Opcode, uint64_t Operand1, uint64_t Operand2) {
103ff0cc061SDimitry Andric     Instructions.push_back(Instruction(Opcode));
104ff0cc061SDimitry Andric     Instructions.back().Ops.push_back(Operand1);
105ff0cc061SDimitry Andric     Instructions.back().Ops.push_back(Operand2);
106ff0cc061SDimitry Andric   }
107ff0cc061SDimitry Andric };
108ff0cc061SDimitry Andric 
109ff0cc061SDimitry Andric // See DWARF standard v3, section 7.23
110ff0cc061SDimitry Andric const uint8_t DWARF_CFI_PRIMARY_OPCODE_MASK = 0xc0;
111ff0cc061SDimitry Andric const uint8_t DWARF_CFI_PRIMARY_OPERAND_MASK = 0x3f;
112ff0cc061SDimitry Andric 
113ff0cc061SDimitry Andric void FrameEntry::parseInstructions(DataExtractor Data, uint32_t *Offset,
114ff0cc061SDimitry Andric                                    uint32_t EndOffset) {
115ff0cc061SDimitry Andric   while (*Offset < EndOffset) {
116ff0cc061SDimitry Andric     uint8_t Opcode = Data.getU8(Offset);
117ff0cc061SDimitry Andric     // Some instructions have a primary opcode encoded in the top bits.
118ff0cc061SDimitry Andric     uint8_t Primary = Opcode & DWARF_CFI_PRIMARY_OPCODE_MASK;
119ff0cc061SDimitry Andric 
120ff0cc061SDimitry Andric     if (Primary) {
121ff0cc061SDimitry Andric       // If it's a primary opcode, the first operand is encoded in the bottom
122ff0cc061SDimitry Andric       // bits of the opcode itself.
123ff0cc061SDimitry Andric       uint64_t Op1 = Opcode & DWARF_CFI_PRIMARY_OPERAND_MASK;
124ff0cc061SDimitry Andric       switch (Primary) {
125ff0cc061SDimitry Andric         default: llvm_unreachable("Impossible primary CFI opcode");
126ff0cc061SDimitry Andric         case DW_CFA_advance_loc:
127ff0cc061SDimitry Andric         case DW_CFA_restore:
128ff0cc061SDimitry Andric           addInstruction(Primary, Op1);
129ff0cc061SDimitry Andric           break;
130ff0cc061SDimitry Andric         case DW_CFA_offset:
131ff0cc061SDimitry Andric           addInstruction(Primary, Op1, Data.getULEB128(Offset));
132ff0cc061SDimitry Andric           break;
133ff0cc061SDimitry Andric       }
134ff0cc061SDimitry Andric     } else {
135ff0cc061SDimitry Andric       // Extended opcode - its value is Opcode itself.
136ff0cc061SDimitry Andric       switch (Opcode) {
137ff0cc061SDimitry Andric         default: llvm_unreachable("Invalid extended CFI opcode");
138ff0cc061SDimitry Andric         case DW_CFA_nop:
139ff0cc061SDimitry Andric         case DW_CFA_remember_state:
140ff0cc061SDimitry Andric         case DW_CFA_restore_state:
141ff0cc061SDimitry Andric         case DW_CFA_GNU_window_save:
142ff0cc061SDimitry Andric           // No operands
143ff0cc061SDimitry Andric           addInstruction(Opcode);
144ff0cc061SDimitry Andric           break;
145ff0cc061SDimitry Andric         case DW_CFA_set_loc:
146ff0cc061SDimitry Andric           // Operands: Address
147ff0cc061SDimitry Andric           addInstruction(Opcode, Data.getAddress(Offset));
148ff0cc061SDimitry Andric           break;
149ff0cc061SDimitry Andric         case DW_CFA_advance_loc1:
150ff0cc061SDimitry Andric           // Operands: 1-byte delta
151ff0cc061SDimitry Andric           addInstruction(Opcode, Data.getU8(Offset));
152ff0cc061SDimitry Andric           break;
153ff0cc061SDimitry Andric         case DW_CFA_advance_loc2:
154ff0cc061SDimitry Andric           // Operands: 2-byte delta
155ff0cc061SDimitry Andric           addInstruction(Opcode, Data.getU16(Offset));
156ff0cc061SDimitry Andric           break;
157ff0cc061SDimitry Andric         case DW_CFA_advance_loc4:
158ff0cc061SDimitry Andric           // Operands: 4-byte delta
159ff0cc061SDimitry Andric           addInstruction(Opcode, Data.getU32(Offset));
160ff0cc061SDimitry Andric           break;
161ff0cc061SDimitry Andric         case DW_CFA_restore_extended:
162ff0cc061SDimitry Andric         case DW_CFA_undefined:
163ff0cc061SDimitry Andric         case DW_CFA_same_value:
164ff0cc061SDimitry Andric         case DW_CFA_def_cfa_register:
165ff0cc061SDimitry Andric         case DW_CFA_def_cfa_offset:
1662cab237bSDimitry Andric         case DW_CFA_GNU_args_size:
167ff0cc061SDimitry Andric           // Operands: ULEB128
168ff0cc061SDimitry Andric           addInstruction(Opcode, Data.getULEB128(Offset));
169ff0cc061SDimitry Andric           break;
170ff0cc061SDimitry Andric         case DW_CFA_def_cfa_offset_sf:
171ff0cc061SDimitry Andric           // Operands: SLEB128
172ff0cc061SDimitry Andric           addInstruction(Opcode, Data.getSLEB128(Offset));
173ff0cc061SDimitry Andric           break;
174ff0cc061SDimitry Andric         case DW_CFA_offset_extended:
175ff0cc061SDimitry Andric         case DW_CFA_register:
176ff0cc061SDimitry Andric         case DW_CFA_def_cfa:
1773ca95b02SDimitry Andric         case DW_CFA_val_offset: {
178ff0cc061SDimitry Andric           // Operands: ULEB128, ULEB128
1793ca95b02SDimitry Andric           // Note: We can not embed getULEB128 directly into function
1803ca95b02SDimitry Andric           // argument list. getULEB128 changes Offset and order of evaluation
1813ca95b02SDimitry Andric           // for arguments is unspecified.
1823ca95b02SDimitry Andric           auto op1 = Data.getULEB128(Offset);
1833ca95b02SDimitry Andric           auto op2 = Data.getULEB128(Offset);
1843ca95b02SDimitry Andric           addInstruction(Opcode, op1, op2);
185ff0cc061SDimitry Andric           break;
1863ca95b02SDimitry Andric         }
187ff0cc061SDimitry Andric         case DW_CFA_offset_extended_sf:
188ff0cc061SDimitry Andric         case DW_CFA_def_cfa_sf:
1893ca95b02SDimitry Andric         case DW_CFA_val_offset_sf: {
190ff0cc061SDimitry Andric           // Operands: ULEB128, SLEB128
1913ca95b02SDimitry Andric           // Note: see comment for the previous case
1923ca95b02SDimitry Andric           auto op1 = Data.getULEB128(Offset);
1933ca95b02SDimitry Andric           auto op2 = (uint64_t)Data.getSLEB128(Offset);
1943ca95b02SDimitry Andric           addInstruction(Opcode, op1, op2);
195ff0cc061SDimitry Andric           break;
1963ca95b02SDimitry Andric         }
197ff0cc061SDimitry Andric         case DW_CFA_def_cfa_expression:
1982cab237bSDimitry Andric           // FIXME: Parse the actual instruction.
1992cab237bSDimitry Andric           *Offset += Data.getULEB128(Offset);
2002cab237bSDimitry Andric           break;
201ff0cc061SDimitry Andric         case DW_CFA_expression:
2022cab237bSDimitry Andric         case DW_CFA_val_expression: {
2032cab237bSDimitry Andric           // FIXME: Parse the actual instruction.
2042cab237bSDimitry Andric           Data.getULEB128(Offset);
2052cab237bSDimitry Andric           *Offset += Data.getULEB128(Offset);
2062cab237bSDimitry Andric           break;
2072cab237bSDimitry Andric         }
208ff0cc061SDimitry Andric       }
209ff0cc061SDimitry Andric     }
210ff0cc061SDimitry Andric   }
211ff0cc061SDimitry Andric }
212ff0cc061SDimitry Andric 
213ff0cc061SDimitry Andric namespace {
214d88c1a5aSDimitry Andric 
215ff0cc061SDimitry Andric /// \brief DWARF Common Information Entry (CIE)
216ff0cc061SDimitry Andric class CIE : public FrameEntry {
217ff0cc061SDimitry Andric public:
218ff0cc061SDimitry Andric   // CIEs (and FDEs) are simply container classes, so the only sensible way to
219ff0cc061SDimitry Andric   // create them is by providing the full parsed contents in the constructor.
220ff0cc061SDimitry Andric   CIE(uint64_t Offset, uint64_t Length, uint8_t Version,
221ff0cc061SDimitry Andric       SmallString<8> Augmentation, uint8_t AddressSize,
222ff0cc061SDimitry Andric       uint8_t SegmentDescriptorSize, uint64_t CodeAlignmentFactor,
2233ca95b02SDimitry Andric       int64_t DataAlignmentFactor, uint64_t ReturnAddressRegister,
2243ca95b02SDimitry Andric       SmallString<8> AugmentationData, uint32_t FDEPointerEncoding,
2253ca95b02SDimitry Andric       uint32_t LSDAPointerEncoding)
226ff0cc061SDimitry Andric       : FrameEntry(FK_CIE, Offset, Length), Version(Version),
2273ca95b02SDimitry Andric         Augmentation(std::move(Augmentation)), AddressSize(AddressSize),
228ff0cc061SDimitry Andric         SegmentDescriptorSize(SegmentDescriptorSize),
229ff0cc061SDimitry Andric         CodeAlignmentFactor(CodeAlignmentFactor),
230ff0cc061SDimitry Andric         DataAlignmentFactor(DataAlignmentFactor),
2313ca95b02SDimitry Andric         ReturnAddressRegister(ReturnAddressRegister),
2323ca95b02SDimitry Andric         AugmentationData(std::move(AugmentationData)),
2333ca95b02SDimitry Andric         FDEPointerEncoding(FDEPointerEncoding),
2343ca95b02SDimitry Andric         LSDAPointerEncoding(LSDAPointerEncoding) {}
235ff0cc061SDimitry Andric 
236d88c1a5aSDimitry Andric   ~CIE() override = default;
237ff0cc061SDimitry Andric 
2383ca95b02SDimitry Andric   StringRef getAugmentationString() const { return Augmentation; }
239ff0cc061SDimitry Andric   uint64_t getCodeAlignmentFactor() const { return CodeAlignmentFactor; }
240ff0cc061SDimitry Andric   int64_t getDataAlignmentFactor() const { return DataAlignmentFactor; }
241d88c1a5aSDimitry Andric 
2423ca95b02SDimitry Andric   uint32_t getFDEPointerEncoding() const {
2433ca95b02SDimitry Andric     return FDEPointerEncoding;
2443ca95b02SDimitry Andric   }
245d88c1a5aSDimitry Andric 
2463ca95b02SDimitry Andric   uint32_t getLSDAPointerEncoding() const {
2473ca95b02SDimitry Andric     return LSDAPointerEncoding;
2483ca95b02SDimitry Andric   }
249ff0cc061SDimitry Andric 
250ff0cc061SDimitry Andric   void dumpHeader(raw_ostream &OS) const override {
251ff0cc061SDimitry Andric     OS << format("%08x %08x %08x CIE",
252ff0cc061SDimitry Andric                  (uint32_t)Offset, (uint32_t)Length, DW_CIE_ID)
253ff0cc061SDimitry Andric        << "\n";
254ff0cc061SDimitry Andric     OS << format("  Version:               %d\n", Version);
255ff0cc061SDimitry Andric     OS << "  Augmentation:          \"" << Augmentation << "\"\n";
256ff0cc061SDimitry Andric     if (Version >= 4) {
257ff0cc061SDimitry Andric       OS << format("  Address size:          %u\n",
258ff0cc061SDimitry Andric                    (uint32_t)AddressSize);
259ff0cc061SDimitry Andric       OS << format("  Segment desc size:     %u\n",
260ff0cc061SDimitry Andric                    (uint32_t)SegmentDescriptorSize);
261ff0cc061SDimitry Andric     }
262ff0cc061SDimitry Andric     OS << format("  Code alignment factor: %u\n",
263ff0cc061SDimitry Andric                  (uint32_t)CodeAlignmentFactor);
264ff0cc061SDimitry Andric     OS << format("  Data alignment factor: %d\n",
265ff0cc061SDimitry Andric                  (int32_t)DataAlignmentFactor);
266ff0cc061SDimitry Andric     OS << format("  Return address column: %d\n",
267ff0cc061SDimitry Andric                  (int32_t)ReturnAddressRegister);
2683ca95b02SDimitry Andric     if (!AugmentationData.empty()) {
2693ca95b02SDimitry Andric       OS << "  Augmentation data:    ";
2703ca95b02SDimitry Andric       for (uint8_t Byte : AugmentationData)
2713ca95b02SDimitry Andric         OS << ' ' << hexdigit(Byte >> 4) << hexdigit(Byte & 0xf);
2723ca95b02SDimitry Andric       OS << "\n";
2733ca95b02SDimitry Andric     }
274ff0cc061SDimitry Andric     OS << "\n";
275ff0cc061SDimitry Andric   }
276ff0cc061SDimitry Andric 
277ff0cc061SDimitry Andric   static bool classof(const FrameEntry *FE) {
278ff0cc061SDimitry Andric     return FE->getKind() == FK_CIE;
279ff0cc061SDimitry Andric   }
280ff0cc061SDimitry Andric 
281ff0cc061SDimitry Andric private:
282ff0cc061SDimitry Andric   /// The following fields are defined in section 6.4.1 of the DWARF standard v4
283ff0cc061SDimitry Andric   uint8_t Version;
284ff0cc061SDimitry Andric   SmallString<8> Augmentation;
285ff0cc061SDimitry Andric   uint8_t AddressSize;
286ff0cc061SDimitry Andric   uint8_t SegmentDescriptorSize;
287ff0cc061SDimitry Andric   uint64_t CodeAlignmentFactor;
288ff0cc061SDimitry Andric   int64_t DataAlignmentFactor;
289ff0cc061SDimitry Andric   uint64_t ReturnAddressRegister;
2903ca95b02SDimitry Andric 
2913ca95b02SDimitry Andric   // The following are used when the CIE represents an EH frame entry.
2923ca95b02SDimitry Andric   SmallString<8> AugmentationData;
2933ca95b02SDimitry Andric   uint32_t FDEPointerEncoding;
2943ca95b02SDimitry Andric   uint32_t LSDAPointerEncoding;
295ff0cc061SDimitry Andric };
296ff0cc061SDimitry Andric 
297ff0cc061SDimitry Andric /// \brief DWARF Frame Description Entry (FDE)
298ff0cc061SDimitry Andric class FDE : public FrameEntry {
299ff0cc061SDimitry Andric public:
300ff0cc061SDimitry Andric   // Each FDE has a CIE it's "linked to". Our FDE contains is constructed with
301ff0cc061SDimitry Andric   // an offset to the CIE (provided by parsing the FDE header). The CIE itself
302ff0cc061SDimitry Andric   // is obtained lazily once it's actually required.
303ff0cc061SDimitry Andric   FDE(uint64_t Offset, uint64_t Length, int64_t LinkedCIEOffset,
304ff0cc061SDimitry Andric       uint64_t InitialLocation, uint64_t AddressRange,
305ff0cc061SDimitry Andric       CIE *Cie)
306ff0cc061SDimitry Andric       : FrameEntry(FK_FDE, Offset, Length), LinkedCIEOffset(LinkedCIEOffset),
307ff0cc061SDimitry Andric         InitialLocation(InitialLocation), AddressRange(AddressRange),
308ff0cc061SDimitry Andric         LinkedCIE(Cie) {}
309ff0cc061SDimitry Andric 
310d88c1a5aSDimitry Andric   ~FDE() override = default;
311ff0cc061SDimitry Andric 
312ff0cc061SDimitry Andric   CIE *getLinkedCIE() const { return LinkedCIE; }
313ff0cc061SDimitry Andric 
314ff0cc061SDimitry Andric   void dumpHeader(raw_ostream &OS) const override {
315ff0cc061SDimitry Andric     OS << format("%08x %08x %08x FDE ",
316ff0cc061SDimitry Andric                  (uint32_t)Offset, (uint32_t)Length, (int32_t)LinkedCIEOffset);
317ff0cc061SDimitry Andric     OS << format("cie=%08x pc=%08x...%08x\n",
318ff0cc061SDimitry Andric                  (int32_t)LinkedCIEOffset,
319ff0cc061SDimitry Andric                  (uint32_t)InitialLocation,
320ff0cc061SDimitry Andric                  (uint32_t)InitialLocation + (uint32_t)AddressRange);
321ff0cc061SDimitry Andric   }
322ff0cc061SDimitry Andric 
323ff0cc061SDimitry Andric   static bool classof(const FrameEntry *FE) {
324ff0cc061SDimitry Andric     return FE->getKind() == FK_FDE;
325ff0cc061SDimitry Andric   }
326ff0cc061SDimitry Andric 
327ff0cc061SDimitry Andric private:
328ff0cc061SDimitry Andric   /// The following fields are defined in section 6.4.1 of the DWARF standard v3
329ff0cc061SDimitry Andric   uint64_t LinkedCIEOffset;
330ff0cc061SDimitry Andric   uint64_t InitialLocation;
331ff0cc061SDimitry Andric   uint64_t AddressRange;
332ff0cc061SDimitry Andric   CIE *LinkedCIE;
333ff0cc061SDimitry Andric };
334ff0cc061SDimitry Andric 
335ff0cc061SDimitry Andric /// \brief Types of operands to CF instructions.
336ff0cc061SDimitry Andric enum OperandType {
337ff0cc061SDimitry Andric   OT_Unset,
338ff0cc061SDimitry Andric   OT_None,
339ff0cc061SDimitry Andric   OT_Address,
340ff0cc061SDimitry Andric   OT_Offset,
341ff0cc061SDimitry Andric   OT_FactoredCodeOffset,
342ff0cc061SDimitry Andric   OT_SignedFactDataOffset,
343ff0cc061SDimitry Andric   OT_UnsignedFactDataOffset,
344ff0cc061SDimitry Andric   OT_Register,
345ff0cc061SDimitry Andric   OT_Expression
346ff0cc061SDimitry Andric };
347ff0cc061SDimitry Andric 
348ff0cc061SDimitry Andric } // end anonymous namespace
349ff0cc061SDimitry Andric 
350ff0cc061SDimitry Andric /// \brief Initialize the array describing the types of operands.
351ff0cc061SDimitry Andric static ArrayRef<OperandType[2]> getOperandTypes() {
352ff0cc061SDimitry Andric   static OperandType OpTypes[DW_CFA_restore+1][2];
353ff0cc061SDimitry Andric 
354ff0cc061SDimitry Andric #define DECLARE_OP2(OP, OPTYPE0, OPTYPE1)       \
355ff0cc061SDimitry Andric   do {                                          \
356ff0cc061SDimitry Andric     OpTypes[OP][0] = OPTYPE0;                   \
357ff0cc061SDimitry Andric     OpTypes[OP][1] = OPTYPE1;                   \
358d88c1a5aSDimitry Andric   } while (false)
359ff0cc061SDimitry Andric #define DECLARE_OP1(OP, OPTYPE0) DECLARE_OP2(OP, OPTYPE0, OT_None)
360ff0cc061SDimitry Andric #define DECLARE_OP0(OP) DECLARE_OP1(OP, OT_None)
361ff0cc061SDimitry Andric 
362ff0cc061SDimitry Andric   DECLARE_OP1(DW_CFA_set_loc, OT_Address);
363ff0cc061SDimitry Andric   DECLARE_OP1(DW_CFA_advance_loc, OT_FactoredCodeOffset);
364ff0cc061SDimitry Andric   DECLARE_OP1(DW_CFA_advance_loc1, OT_FactoredCodeOffset);
365ff0cc061SDimitry Andric   DECLARE_OP1(DW_CFA_advance_loc2, OT_FactoredCodeOffset);
366ff0cc061SDimitry Andric   DECLARE_OP1(DW_CFA_advance_loc4, OT_FactoredCodeOffset);
367ff0cc061SDimitry Andric   DECLARE_OP1(DW_CFA_MIPS_advance_loc8, OT_FactoredCodeOffset);
368ff0cc061SDimitry Andric   DECLARE_OP2(DW_CFA_def_cfa, OT_Register, OT_Offset);
369ff0cc061SDimitry Andric   DECLARE_OP2(DW_CFA_def_cfa_sf, OT_Register, OT_SignedFactDataOffset);
370ff0cc061SDimitry Andric   DECLARE_OP1(DW_CFA_def_cfa_register, OT_Register);
371ff0cc061SDimitry Andric   DECLARE_OP1(DW_CFA_def_cfa_offset, OT_Offset);
372ff0cc061SDimitry Andric   DECLARE_OP1(DW_CFA_def_cfa_offset_sf, OT_SignedFactDataOffset);
373ff0cc061SDimitry Andric   DECLARE_OP1(DW_CFA_def_cfa_expression, OT_Expression);
374ff0cc061SDimitry Andric   DECLARE_OP1(DW_CFA_undefined, OT_Register);
375ff0cc061SDimitry Andric   DECLARE_OP1(DW_CFA_same_value, OT_Register);
376ff0cc061SDimitry Andric   DECLARE_OP2(DW_CFA_offset, OT_Register, OT_UnsignedFactDataOffset);
377ff0cc061SDimitry Andric   DECLARE_OP2(DW_CFA_offset_extended, OT_Register, OT_UnsignedFactDataOffset);
378ff0cc061SDimitry Andric   DECLARE_OP2(DW_CFA_offset_extended_sf, OT_Register, OT_SignedFactDataOffset);
379ff0cc061SDimitry Andric   DECLARE_OP2(DW_CFA_val_offset, OT_Register, OT_UnsignedFactDataOffset);
380ff0cc061SDimitry Andric   DECLARE_OP2(DW_CFA_val_offset_sf, OT_Register, OT_SignedFactDataOffset);
381ff0cc061SDimitry Andric   DECLARE_OP2(DW_CFA_register, OT_Register, OT_Register);
382ff0cc061SDimitry Andric   DECLARE_OP2(DW_CFA_expression, OT_Register, OT_Expression);
383ff0cc061SDimitry Andric   DECLARE_OP2(DW_CFA_val_expression, OT_Register, OT_Expression);
384ff0cc061SDimitry Andric   DECLARE_OP1(DW_CFA_restore, OT_Register);
385ff0cc061SDimitry Andric   DECLARE_OP1(DW_CFA_restore_extended, OT_Register);
386ff0cc061SDimitry Andric   DECLARE_OP0(DW_CFA_remember_state);
387ff0cc061SDimitry Andric   DECLARE_OP0(DW_CFA_restore_state);
388ff0cc061SDimitry Andric   DECLARE_OP0(DW_CFA_GNU_window_save);
389ff0cc061SDimitry Andric   DECLARE_OP1(DW_CFA_GNU_args_size, OT_Offset);
390ff0cc061SDimitry Andric   DECLARE_OP0(DW_CFA_nop);
391ff0cc061SDimitry Andric 
392ff0cc061SDimitry Andric #undef DECLARE_OP0
393ff0cc061SDimitry Andric #undef DECLARE_OP1
394ff0cc061SDimitry Andric #undef DECLARE_OP2
395d88c1a5aSDimitry Andric 
396ff0cc061SDimitry Andric   return ArrayRef<OperandType[2]>(&OpTypes[0], DW_CFA_restore+1);
397ff0cc061SDimitry Andric }
398ff0cc061SDimitry Andric 
399ff0cc061SDimitry Andric static ArrayRef<OperandType[2]> OpTypes = getOperandTypes();
400ff0cc061SDimitry Andric 
401ff0cc061SDimitry Andric /// \brief Print \p Opcode's operand number \p OperandIdx which has
402ff0cc061SDimitry Andric /// value \p Operand.
403ff0cc061SDimitry Andric static void printOperand(raw_ostream &OS, uint8_t Opcode, unsigned OperandIdx,
404ff0cc061SDimitry Andric                          uint64_t Operand, uint64_t CodeAlignmentFactor,
405ff0cc061SDimitry Andric                          int64_t DataAlignmentFactor) {
406ff0cc061SDimitry Andric   assert(OperandIdx < 2);
407ff0cc061SDimitry Andric   OperandType Type = OpTypes[Opcode][OperandIdx];
408ff0cc061SDimitry Andric 
409ff0cc061SDimitry Andric   switch (Type) {
410d88c1a5aSDimitry Andric   case OT_Unset: {
411ff0cc061SDimitry Andric     OS << " Unsupported " << (OperandIdx ? "second" : "first") << " operand to";
412d88c1a5aSDimitry Andric     auto OpcodeName = CallFrameString(Opcode);
413d88c1a5aSDimitry Andric     if (!OpcodeName.empty())
414ff0cc061SDimitry Andric       OS << " " << OpcodeName;
415ff0cc061SDimitry Andric     else
416ff0cc061SDimitry Andric       OS << format(" Opcode %x",  Opcode);
417ff0cc061SDimitry Andric     break;
418d88c1a5aSDimitry Andric   }
419ff0cc061SDimitry Andric   case OT_None:
420ff0cc061SDimitry Andric     break;
421ff0cc061SDimitry Andric   case OT_Address:
422ff0cc061SDimitry Andric     OS << format(" %" PRIx64, Operand);
423ff0cc061SDimitry Andric     break;
424ff0cc061SDimitry Andric   case OT_Offset:
425ff0cc061SDimitry Andric     // The offsets are all encoded in a unsigned form, but in practice
426ff0cc061SDimitry Andric     // consumers use them signed. It's most certainly legacy due to
427ff0cc061SDimitry Andric     // the lack of signed variants in the first Dwarf standards.
428ff0cc061SDimitry Andric     OS << format(" %+" PRId64, int64_t(Operand));
429ff0cc061SDimitry Andric     break;
430ff0cc061SDimitry Andric   case OT_FactoredCodeOffset: // Always Unsigned
431ff0cc061SDimitry Andric     if (CodeAlignmentFactor)
432ff0cc061SDimitry Andric       OS << format(" %" PRId64, Operand * CodeAlignmentFactor);
433ff0cc061SDimitry Andric     else
434ff0cc061SDimitry Andric       OS << format(" %" PRId64 "*code_alignment_factor" , Operand);
435ff0cc061SDimitry Andric     break;
436ff0cc061SDimitry Andric   case OT_SignedFactDataOffset:
437ff0cc061SDimitry Andric     if (DataAlignmentFactor)
438ff0cc061SDimitry Andric       OS << format(" %" PRId64, int64_t(Operand) * DataAlignmentFactor);
439ff0cc061SDimitry Andric     else
440ff0cc061SDimitry Andric       OS << format(" %" PRId64 "*data_alignment_factor" , int64_t(Operand));
441ff0cc061SDimitry Andric     break;
442ff0cc061SDimitry Andric   case OT_UnsignedFactDataOffset:
443ff0cc061SDimitry Andric     if (DataAlignmentFactor)
444ff0cc061SDimitry Andric       OS << format(" %" PRId64, Operand * DataAlignmentFactor);
445ff0cc061SDimitry Andric     else
446ff0cc061SDimitry Andric       OS << format(" %" PRId64 "*data_alignment_factor" , Operand);
447ff0cc061SDimitry Andric     break;
448ff0cc061SDimitry Andric   case OT_Register:
449ff0cc061SDimitry Andric     OS << format(" reg%" PRId64, Operand);
450ff0cc061SDimitry Andric     break;
451ff0cc061SDimitry Andric   case OT_Expression:
452ff0cc061SDimitry Andric     OS << " expression";
453ff0cc061SDimitry Andric     break;
454ff0cc061SDimitry Andric   }
455ff0cc061SDimitry Andric }
456ff0cc061SDimitry Andric 
457ff0cc061SDimitry Andric void FrameEntry::dumpInstructions(raw_ostream &OS) const {
458ff0cc061SDimitry Andric   uint64_t CodeAlignmentFactor = 0;
459ff0cc061SDimitry Andric   int64_t DataAlignmentFactor = 0;
460ff0cc061SDimitry Andric   const CIE *Cie = dyn_cast<CIE>(this);
461ff0cc061SDimitry Andric 
462ff0cc061SDimitry Andric   if (!Cie)
463ff0cc061SDimitry Andric     Cie = cast<FDE>(this)->getLinkedCIE();
464ff0cc061SDimitry Andric   if (Cie) {
465ff0cc061SDimitry Andric     CodeAlignmentFactor = Cie->getCodeAlignmentFactor();
466ff0cc061SDimitry Andric     DataAlignmentFactor = Cie->getDataAlignmentFactor();
467ff0cc061SDimitry Andric   }
468ff0cc061SDimitry Andric 
469ff0cc061SDimitry Andric   for (const auto &Instr : Instructions) {
470ff0cc061SDimitry Andric     uint8_t Opcode = Instr.Opcode;
471ff0cc061SDimitry Andric     if (Opcode & DWARF_CFI_PRIMARY_OPCODE_MASK)
472ff0cc061SDimitry Andric       Opcode &= DWARF_CFI_PRIMARY_OPCODE_MASK;
473ff0cc061SDimitry Andric     OS << "  " << CallFrameString(Opcode) << ":";
474ff0cc061SDimitry Andric     for (unsigned i = 0; i < Instr.Ops.size(); ++i)
475ff0cc061SDimitry Andric       printOperand(OS, Opcode, i, Instr.Ops[i], CodeAlignmentFactor,
476ff0cc061SDimitry Andric                    DataAlignmentFactor);
477ff0cc061SDimitry Andric     OS << '\n';
478ff0cc061SDimitry Andric   }
479ff0cc061SDimitry Andric }
480ff0cc061SDimitry Andric 
4817a7e6055SDimitry Andric DWARFDebugFrame::DWARFDebugFrame(bool IsEH) : IsEH(IsEH) {}
482ff0cc061SDimitry Andric 
483d88c1a5aSDimitry Andric DWARFDebugFrame::~DWARFDebugFrame() = default;
484ff0cc061SDimitry Andric 
485ff0cc061SDimitry Andric static void LLVM_ATTRIBUTE_UNUSED dumpDataAux(DataExtractor Data,
486ff0cc061SDimitry Andric                                               uint32_t Offset, int Length) {
487ff0cc061SDimitry Andric   errs() << "DUMP: ";
488ff0cc061SDimitry Andric   for (int i = 0; i < Length; ++i) {
489ff0cc061SDimitry Andric     uint8_t c = Data.getU8(&Offset);
490ff0cc061SDimitry Andric     errs().write_hex(c); errs() << " ";
491ff0cc061SDimitry Andric   }
492ff0cc061SDimitry Andric   errs() << "\n";
493ff0cc061SDimitry Andric }
494ff0cc061SDimitry Andric 
4953ca95b02SDimitry Andric static unsigned getSizeForEncoding(const DataExtractor &Data,
4963ca95b02SDimitry Andric                                    unsigned symbolEncoding) {
4973ca95b02SDimitry Andric   unsigned format = symbolEncoding & 0x0f;
4983ca95b02SDimitry Andric   switch (format) {
4993ca95b02SDimitry Andric     default: llvm_unreachable("Unknown Encoding");
5007a7e6055SDimitry Andric     case DW_EH_PE_absptr:
5017a7e6055SDimitry Andric     case DW_EH_PE_signed:
5023ca95b02SDimitry Andric       return Data.getAddressSize();
5037a7e6055SDimitry Andric     case DW_EH_PE_udata2:
5047a7e6055SDimitry Andric     case DW_EH_PE_sdata2:
5053ca95b02SDimitry Andric       return 2;
5067a7e6055SDimitry Andric     case DW_EH_PE_udata4:
5077a7e6055SDimitry Andric     case DW_EH_PE_sdata4:
5083ca95b02SDimitry Andric       return 4;
5097a7e6055SDimitry Andric     case DW_EH_PE_udata8:
5107a7e6055SDimitry Andric     case DW_EH_PE_sdata8:
5113ca95b02SDimitry Andric       return 8;
5123ca95b02SDimitry Andric   }
5133ca95b02SDimitry Andric }
5143ca95b02SDimitry Andric 
5153ca95b02SDimitry Andric static uint64_t readPointer(const DataExtractor &Data, uint32_t &Offset,
5163ca95b02SDimitry Andric                             unsigned Encoding) {
5173ca95b02SDimitry Andric   switch (getSizeForEncoding(Data, Encoding)) {
5183ca95b02SDimitry Andric     case 2:
5193ca95b02SDimitry Andric       return Data.getU16(&Offset);
5203ca95b02SDimitry Andric     case 4:
5213ca95b02SDimitry Andric       return Data.getU32(&Offset);
5223ca95b02SDimitry Andric     case 8:
5233ca95b02SDimitry Andric       return Data.getU64(&Offset);
5243ca95b02SDimitry Andric     default:
5253ca95b02SDimitry Andric       llvm_unreachable("Illegal data size");
5263ca95b02SDimitry Andric   }
5273ca95b02SDimitry Andric }
528ff0cc061SDimitry Andric 
52924d58133SDimitry Andric // This is a workaround for old compilers which do not allow
53024d58133SDimitry Andric // noreturn attribute usage in lambdas. Once the support for those
53124d58133SDimitry Andric // compilers are phased out, we can remove this and return back to
53224d58133SDimitry Andric // a ReportError lambda: [StartOffset](const char *ErrorMsg).
533edd7eaddSDimitry Andric static void LLVM_ATTRIBUTE_NORETURN ReportError(uint32_t StartOffset,
534edd7eaddSDimitry Andric                                                 const char *ErrorMsg) {
53524d58133SDimitry Andric   std::string Str;
53624d58133SDimitry Andric   raw_string_ostream OS(Str);
53724d58133SDimitry Andric   OS << format(ErrorMsg, StartOffset);
53824d58133SDimitry Andric   OS.flush();
53924d58133SDimitry Andric   report_fatal_error(Str);
54024d58133SDimitry Andric }
54124d58133SDimitry Andric 
542ff0cc061SDimitry Andric void DWARFDebugFrame::parse(DataExtractor Data) {
543ff0cc061SDimitry Andric   uint32_t Offset = 0;
544ff0cc061SDimitry Andric   DenseMap<uint32_t, CIE *> CIEs;
545ff0cc061SDimitry Andric 
546ff0cc061SDimitry Andric   while (Data.isValidOffset(Offset)) {
547ff0cc061SDimitry Andric     uint32_t StartOffset = Offset;
548ff0cc061SDimitry Andric 
549ff0cc061SDimitry Andric     bool IsDWARF64 = false;
550ff0cc061SDimitry Andric     uint64_t Length = Data.getU32(&Offset);
551ff0cc061SDimitry Andric     uint64_t Id;
552ff0cc061SDimitry Andric 
553ff0cc061SDimitry Andric     if (Length == UINT32_MAX) {
554ff0cc061SDimitry Andric       // DWARF-64 is distinguished by the first 32 bits of the initial length
555ff0cc061SDimitry Andric       // field being 0xffffffff. Then, the next 64 bits are the actual entry
556ff0cc061SDimitry Andric       // length.
557ff0cc061SDimitry Andric       IsDWARF64 = true;
558ff0cc061SDimitry Andric       Length = Data.getU64(&Offset);
559ff0cc061SDimitry Andric     }
560ff0cc061SDimitry Andric 
561ff0cc061SDimitry Andric     // At this point, Offset points to the next field after Length.
562ff0cc061SDimitry Andric     // Length is the structure size excluding itself. Compute an offset one
563ff0cc061SDimitry Andric     // past the end of the structure (needed to know how many instructions to
564ff0cc061SDimitry Andric     // read).
565ff0cc061SDimitry Andric     // TODO: For honest DWARF64 support, DataExtractor will have to treat
566ff0cc061SDimitry Andric     //       offset_ptr as uint64_t*
5673ca95b02SDimitry Andric     uint32_t StartStructureOffset = Offset;
568ff0cc061SDimitry Andric     uint32_t EndStructureOffset = Offset + static_cast<uint32_t>(Length);
569ff0cc061SDimitry Andric 
570ff0cc061SDimitry Andric     // The Id field's size depends on the DWARF format
5713ca95b02SDimitry Andric     Id = Data.getUnsigned(&Offset, (IsDWARF64 && !IsEH) ? 8 : 4);
5723ca95b02SDimitry Andric     bool IsCIE = ((IsDWARF64 && Id == DW64_CIE_ID) ||
5733ca95b02SDimitry Andric                   Id == DW_CIE_ID ||
5743ca95b02SDimitry Andric                   (IsEH && !Id));
575ff0cc061SDimitry Andric 
576ff0cc061SDimitry Andric     if (IsCIE) {
577ff0cc061SDimitry Andric       uint8_t Version = Data.getU8(&Offset);
578ff0cc061SDimitry Andric       const char *Augmentation = Data.getCStr(&Offset);
5793ca95b02SDimitry Andric       StringRef AugmentationString(Augmentation ? Augmentation : "");
5803ca95b02SDimitry Andric       uint8_t AddressSize = Version < 4 ? Data.getAddressSize() :
5813ca95b02SDimitry Andric                                           Data.getU8(&Offset);
582ff0cc061SDimitry Andric       Data.setAddressSize(AddressSize);
583ff0cc061SDimitry Andric       uint8_t SegmentDescriptorSize = Version < 4 ? 0 : Data.getU8(&Offset);
584ff0cc061SDimitry Andric       uint64_t CodeAlignmentFactor = Data.getULEB128(&Offset);
585ff0cc061SDimitry Andric       int64_t DataAlignmentFactor = Data.getSLEB128(&Offset);
586ff0cc061SDimitry Andric       uint64_t ReturnAddressRegister = Data.getULEB128(&Offset);
587ff0cc061SDimitry Andric 
5883ca95b02SDimitry Andric       // Parse the augmentation data for EH CIEs
5893ca95b02SDimitry Andric       StringRef AugmentationData("");
5903ca95b02SDimitry Andric       uint32_t FDEPointerEncoding = DW_EH_PE_omit;
5913ca95b02SDimitry Andric       uint32_t LSDAPointerEncoding = DW_EH_PE_omit;
5923ca95b02SDimitry Andric       if (IsEH) {
5933ca95b02SDimitry Andric         Optional<uint32_t> PersonalityEncoding;
5943ca95b02SDimitry Andric         Optional<uint64_t> Personality;
5953ca95b02SDimitry Andric 
5963ca95b02SDimitry Andric         Optional<uint64_t> AugmentationLength;
5973ca95b02SDimitry Andric         uint32_t StartAugmentationOffset;
5983ca95b02SDimitry Andric         uint32_t EndAugmentationOffset;
5993ca95b02SDimitry Andric 
6003ca95b02SDimitry Andric         // Walk the augmentation string to get all the augmentation data.
6013ca95b02SDimitry Andric         for (unsigned i = 0, e = AugmentationString.size(); i != e; ++i) {
6023ca95b02SDimitry Andric           switch (AugmentationString[i]) {
6033ca95b02SDimitry Andric             default:
604edd7eaddSDimitry Andric               ReportError(StartOffset,
605edd7eaddSDimitry Andric                           "Unknown augmentation character in entry at %lx");
6063ca95b02SDimitry Andric             case 'L':
6073ca95b02SDimitry Andric               LSDAPointerEncoding = Data.getU8(&Offset);
6083ca95b02SDimitry Andric               break;
6093ca95b02SDimitry Andric             case 'P': {
6103ca95b02SDimitry Andric               if (Personality)
611edd7eaddSDimitry Andric                 ReportError(StartOffset,
612edd7eaddSDimitry Andric                             "Duplicate personality in entry at %lx");
6133ca95b02SDimitry Andric               PersonalityEncoding = Data.getU8(&Offset);
6143ca95b02SDimitry Andric               Personality = readPointer(Data, Offset, *PersonalityEncoding);
6153ca95b02SDimitry Andric               break;
6163ca95b02SDimitry Andric             }
6173ca95b02SDimitry Andric             case 'R':
6183ca95b02SDimitry Andric               FDEPointerEncoding = Data.getU8(&Offset);
6193ca95b02SDimitry Andric               break;
6203ca95b02SDimitry Andric             case 'z':
6213ca95b02SDimitry Andric               if (i)
622edd7eaddSDimitry Andric                 ReportError(StartOffset,
623edd7eaddSDimitry Andric                             "'z' must be the first character at %lx");
6243ca95b02SDimitry Andric               // Parse the augmentation length first.  We only parse it if
6253ca95b02SDimitry Andric               // the string contains a 'z'.
6263ca95b02SDimitry Andric               AugmentationLength = Data.getULEB128(&Offset);
6273ca95b02SDimitry Andric               StartAugmentationOffset = Offset;
6283ca95b02SDimitry Andric               EndAugmentationOffset = Offset +
6293ca95b02SDimitry Andric                 static_cast<uint32_t>(*AugmentationLength);
6303ca95b02SDimitry Andric           }
6313ca95b02SDimitry Andric         }
6323ca95b02SDimitry Andric 
6333ca95b02SDimitry Andric         if (AugmentationLength.hasValue()) {
6343ca95b02SDimitry Andric           if (Offset != EndAugmentationOffset)
635edd7eaddSDimitry Andric             ReportError(StartOffset, "Parsing augmentation data at %lx failed");
6363ca95b02SDimitry Andric 
6373ca95b02SDimitry Andric           AugmentationData = Data.getData().slice(StartAugmentationOffset,
6383ca95b02SDimitry Andric                                                   EndAugmentationOffset);
6393ca95b02SDimitry Andric         }
6403ca95b02SDimitry Andric       }
6413ca95b02SDimitry Andric 
642d88c1a5aSDimitry Andric       auto Cie = llvm::make_unique<CIE>(StartOffset, Length, Version,
6433ca95b02SDimitry Andric                                         AugmentationString, AddressSize,
644d88c1a5aSDimitry Andric                                         SegmentDescriptorSize,
645d88c1a5aSDimitry Andric                                         CodeAlignmentFactor,
646d88c1a5aSDimitry Andric                                         DataAlignmentFactor,
647d88c1a5aSDimitry Andric                                         ReturnAddressRegister,
6483ca95b02SDimitry Andric                                         AugmentationData, FDEPointerEncoding,
6493ca95b02SDimitry Andric                                         LSDAPointerEncoding);
650ff0cc061SDimitry Andric       CIEs[StartOffset] = Cie.get();
651ff0cc061SDimitry Andric       Entries.emplace_back(std::move(Cie));
652ff0cc061SDimitry Andric     } else {
653ff0cc061SDimitry Andric       // FDE
654ff0cc061SDimitry Andric       uint64_t CIEPointer = Id;
6553ca95b02SDimitry Andric       uint64_t InitialLocation = 0;
6563ca95b02SDimitry Andric       uint64_t AddressRange = 0;
6573ca95b02SDimitry Andric       CIE *Cie = CIEs[IsEH ? (StartStructureOffset - CIEPointer) : CIEPointer];
6583ca95b02SDimitry Andric 
6593ca95b02SDimitry Andric       if (IsEH) {
6603ca95b02SDimitry Andric         // The address size is encoded in the CIE we reference.
6613ca95b02SDimitry Andric         if (!Cie)
662edd7eaddSDimitry Andric           ReportError(StartOffset,
663edd7eaddSDimitry Andric                       "Parsing FDE data at %lx failed due to missing CIE");
6643ca95b02SDimitry Andric 
6653ca95b02SDimitry Andric         InitialLocation = readPointer(Data, Offset,
6663ca95b02SDimitry Andric                                       Cie->getFDEPointerEncoding());
6673ca95b02SDimitry Andric         AddressRange = readPointer(Data, Offset,
6683ca95b02SDimitry Andric                                    Cie->getFDEPointerEncoding());
6693ca95b02SDimitry Andric 
6703ca95b02SDimitry Andric         StringRef AugmentationString = Cie->getAugmentationString();
6713ca95b02SDimitry Andric         if (!AugmentationString.empty()) {
6723ca95b02SDimitry Andric           // Parse the augmentation length and data for this FDE.
6733ca95b02SDimitry Andric           uint64_t AugmentationLength = Data.getULEB128(&Offset);
6743ca95b02SDimitry Andric 
6753ca95b02SDimitry Andric           uint32_t EndAugmentationOffset =
6763ca95b02SDimitry Andric             Offset + static_cast<uint32_t>(AugmentationLength);
6773ca95b02SDimitry Andric 
6783ca95b02SDimitry Andric           // Decode the LSDA if the CIE augmentation string said we should.
6793ca95b02SDimitry Andric           if (Cie->getLSDAPointerEncoding() != DW_EH_PE_omit)
6803ca95b02SDimitry Andric             readPointer(Data, Offset, Cie->getLSDAPointerEncoding());
6813ca95b02SDimitry Andric 
6823ca95b02SDimitry Andric           if (Offset != EndAugmentationOffset)
683edd7eaddSDimitry Andric             ReportError(StartOffset, "Parsing augmentation data at %lx failed");
6843ca95b02SDimitry Andric         }
6853ca95b02SDimitry Andric       } else {
6863ca95b02SDimitry Andric         InitialLocation = Data.getAddress(&Offset);
6873ca95b02SDimitry Andric         AddressRange = Data.getAddress(&Offset);
6883ca95b02SDimitry Andric       }
689ff0cc061SDimitry Andric 
690ff0cc061SDimitry Andric       Entries.emplace_back(new FDE(StartOffset, Length, CIEPointer,
691ff0cc061SDimitry Andric                                    InitialLocation, AddressRange,
6923ca95b02SDimitry Andric                                    Cie));
693ff0cc061SDimitry Andric     }
694ff0cc061SDimitry Andric 
695ff0cc061SDimitry Andric     Entries.back()->parseInstructions(Data, &Offset, EndStructureOffset);
696ff0cc061SDimitry Andric 
6973ca95b02SDimitry Andric     if (Offset != EndStructureOffset)
698edd7eaddSDimitry Andric       ReportError(StartOffset, "Parsing entry instructions at %lx failed");
699ff0cc061SDimitry Andric   }
700ff0cc061SDimitry Andric }
701ff0cc061SDimitry Andric 
7022cab237bSDimitry Andric FrameEntry *DWARFDebugFrame::getEntryAtOffset(uint64_t Offset) const {
7032cab237bSDimitry Andric   auto It =
7042cab237bSDimitry Andric       std::lower_bound(Entries.begin(), Entries.end(), Offset,
7052cab237bSDimitry Andric                        [](const std::unique_ptr<FrameEntry> &E,
7062cab237bSDimitry Andric                           uint64_t Offset) { return E->getOffset() < Offset; });
7072cab237bSDimitry Andric   if (It != Entries.end() && (*It)->getOffset() == Offset)
7082cab237bSDimitry Andric     return It->get();
7092cab237bSDimitry Andric   return nullptr;
710ff0cc061SDimitry Andric }
7112cab237bSDimitry Andric 
7122cab237bSDimitry Andric void DWARFDebugFrame::dump(raw_ostream &OS, Optional<uint64_t> Offset) const {
7132cab237bSDimitry Andric   if (Offset) {
7142cab237bSDimitry Andric     if (auto *Entry = getEntryAtOffset(*Offset))
7152cab237bSDimitry Andric       Entry->dump(OS);
7162cab237bSDimitry Andric     return;
7172cab237bSDimitry Andric   }
7182cab237bSDimitry Andric 
7192cab237bSDimitry Andric   OS << "\n";
7202cab237bSDimitry Andric   for (const auto &Entry : Entries)
7212cab237bSDimitry Andric     Entry->dump(OS);
722ff0cc061SDimitry Andric }
723