1//===- DWARFDebugFrame.h - Parsing of .debug_frame --------------*- C++ -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9#ifndef LLVM_DEBUGINFO_DWARF_DWARFDEBUGFRAME_H
10#define LLVM_DEBUGINFO_DWARF_DWARFDEBUGFRAME_H
11
12#include "llvm/ADT/ArrayRef.h"
13#include "llvm/ADT/iterator.h"
14#include "llvm/ADT/SmallString.h"
15#include "llvm/ADT/Triple.h"
16#include "llvm/DebugInfo/DWARF/DWARFDataExtractor.h"
17#include "llvm/DebugInfo/DWARF/DWARFExpression.h"
18#include "llvm/Support/Error.h"
19#include <memory>
20#include <vector>
21
22namespace llvm {
23
24class raw_ostream;
25
26namespace dwarf {
27
28/// Represent a sequence of Call Frame Information instructions that, when read
29/// in order, construct a table mapping PC to frame state. This can also be
30/// referred to as "CFI rules" in DWARF literature to avoid confusion with
31/// computer programs in the broader sense, and in this context each instruction
32/// would be a rule to establish the mapping. Refer to pg. 172 in the DWARF5
33/// manual, "6.4.1 Structure of Call Frame Information".
34class CFIProgram {
35public:
36  typedef SmallVector<uint64_t, 2> Operands;
37
38  /// An instruction consists of a DWARF CFI opcode and an optional sequence of
39  /// operands. If it refers to an expression, then this expression has its own
40  /// sequence of operations and operands handled separately by DWARFExpression.
41  struct Instruction {
42    Instruction(uint8_t Opcode) : Opcode(Opcode) {}
43
44    uint8_t Opcode;
45    Operands Ops;
46    // Associated DWARF expression in case this instruction refers to one
47    Optional<DWARFExpression> Expression;
48  };
49
50  using InstrList = std::vector<Instruction>;
51  using iterator = InstrList::iterator;
52  using const_iterator = InstrList::const_iterator;
53
54  iterator begin() { return Instructions.begin(); }
55  const_iterator begin() const { return Instructions.begin(); }
56  iterator end() { return Instructions.end(); }
57  const_iterator end() const { return Instructions.end(); }
58
59  unsigned size() const { return (unsigned)Instructions.size(); }
60  bool empty() const { return Instructions.empty(); }
61
62  CFIProgram(uint64_t CodeAlignmentFactor, int64_t DataAlignmentFactor,
63             Triple::ArchType Arch)
64      : CodeAlignmentFactor(CodeAlignmentFactor),
65        DataAlignmentFactor(DataAlignmentFactor),
66        Arch(Arch) {}
67
68  /// Parse and store a sequence of CFI instructions from Data,
69  /// starting at *Offset and ending at EndOffset. *Offset is updated
70  /// to EndOffset upon successful parsing, or indicates the offset
71  /// where a problem occurred in case an error is returned.
72  Error parse(DWARFDataExtractor Data, uint64_t *Offset, uint64_t EndOffset);
73
74  void dump(raw_ostream &OS, const MCRegisterInfo *MRI, bool IsEH,
75            unsigned IndentLevel = 1) const;
76
77private:
78  std::vector<Instruction> Instructions;
79  const uint64_t CodeAlignmentFactor;
80  const int64_t DataAlignmentFactor;
81  Triple::ArchType Arch;
82
83  /// Convenience method to add a new instruction with the given opcode.
84  void addInstruction(uint8_t Opcode) {
85    Instructions.push_back(Instruction(Opcode));
86  }
87
88  /// Add a new single-operand instruction.
89  void addInstruction(uint8_t Opcode, uint64_t Operand1) {
90    Instructions.push_back(Instruction(Opcode));
91    Instructions.back().Ops.push_back(Operand1);
92  }
93
94  /// Add a new instruction that has two operands.
95  void addInstruction(uint8_t Opcode, uint64_t Operand1, uint64_t Operand2) {
96    Instructions.push_back(Instruction(Opcode));
97    Instructions.back().Ops.push_back(Operand1);
98    Instructions.back().Ops.push_back(Operand2);
99  }
100
101  /// Types of operands to CFI instructions
102  /// In DWARF, this type is implicitly tied to a CFI instruction opcode and
103  /// thus this type doesn't need to be explictly written to the file (this is
104  /// not a DWARF encoding). The relationship of instrs to operand types can
105  /// be obtained from getOperandTypes() and is only used to simplify
106  /// instruction printing.
107  enum OperandType {
108    OT_Unset,
109    OT_None,
110    OT_Address,
111    OT_Offset,
112    OT_FactoredCodeOffset,
113    OT_SignedFactDataOffset,
114    OT_UnsignedFactDataOffset,
115    OT_Register,
116    OT_Expression
117  };
118
119  /// Retrieve the array describing the types of operands according to the enum
120  /// above. This is indexed by opcode.
121  static ArrayRef<OperandType[2]> getOperandTypes();
122
123  /// Print \p Opcode's operand number \p OperandIdx which has value \p Operand.
124  void printOperand(raw_ostream &OS, const MCRegisterInfo *MRI, bool IsEH,
125                    const Instruction &Instr, unsigned OperandIdx,
126                    uint64_t Operand) const;
127};
128
129/// An entry in either debug_frame or eh_frame. This entry can be a CIE or an
130/// FDE.
131class FrameEntry {
132public:
133  enum FrameKind { FK_CIE, FK_FDE };
134
135  FrameEntry(FrameKind K, uint64_t Offset, uint64_t Length, uint64_t CodeAlign,
136             int64_t DataAlign, Triple::ArchType Arch)
137      : Kind(K), Offset(Offset), Length(Length),
138        CFIs(CodeAlign, DataAlign, Arch) {}
139
140  virtual ~FrameEntry() {}
141
142  FrameKind getKind() const { return Kind; }
143  uint64_t getOffset() const { return Offset; }
144  uint64_t getLength() const { return Length; }
145  const CFIProgram &cfis() const { return CFIs; }
146  CFIProgram &cfis() { return CFIs; }
147
148  /// Dump the instructions in this CFI fragment
149  virtual void dump(raw_ostream &OS, const MCRegisterInfo *MRI,
150                    bool IsEH) const = 0;
151
152protected:
153  const FrameKind Kind;
154
155  /// Offset of this entry in the section.
156  const uint64_t Offset;
157
158  /// Entry length as specified in DWARF.
159  const uint64_t Length;
160
161  CFIProgram CFIs;
162};
163
164/// DWARF Common Information Entry (CIE)
165class CIE : public FrameEntry {
166public:
167  // CIEs (and FDEs) are simply container classes, so the only sensible way to
168  // create them is by providing the full parsed contents in the constructor.
169  CIE(uint64_t Offset, uint64_t Length, uint8_t Version,
170      SmallString<8> Augmentation, uint8_t AddressSize,
171      uint8_t SegmentDescriptorSize, uint64_t CodeAlignmentFactor,
172      int64_t DataAlignmentFactor, uint64_t ReturnAddressRegister,
173      SmallString<8> AugmentationData, uint32_t FDEPointerEncoding,
174      uint32_t LSDAPointerEncoding, Optional<uint64_t> Personality,
175      Optional<uint32_t> PersonalityEnc, Triple::ArchType Arch)
176      : FrameEntry(FK_CIE, Offset, Length, CodeAlignmentFactor,
177                   DataAlignmentFactor, Arch),
178        Version(Version), Augmentation(std::move(Augmentation)),
179        AddressSize(AddressSize), SegmentDescriptorSize(SegmentDescriptorSize),
180        CodeAlignmentFactor(CodeAlignmentFactor),
181        DataAlignmentFactor(DataAlignmentFactor),
182        ReturnAddressRegister(ReturnAddressRegister),
183        AugmentationData(std::move(AugmentationData)),
184        FDEPointerEncoding(FDEPointerEncoding),
185        LSDAPointerEncoding(LSDAPointerEncoding), Personality(Personality),
186        PersonalityEnc(PersonalityEnc) {}
187
188  static bool classof(const FrameEntry *FE) { return FE->getKind() == FK_CIE; }
189
190  StringRef getAugmentationString() const { return Augmentation; }
191  uint64_t getCodeAlignmentFactor() const { return CodeAlignmentFactor; }
192  int64_t getDataAlignmentFactor() const { return DataAlignmentFactor; }
193  uint8_t getVersion() const { return Version; }
194  uint64_t getReturnAddressRegister() const { return ReturnAddressRegister; }
195  Optional<uint64_t> getPersonalityAddress() const { return Personality; }
196  Optional<uint32_t> getPersonalityEncoding() const { return PersonalityEnc; }
197
198  uint32_t getFDEPointerEncoding() const { return FDEPointerEncoding; }
199
200  uint32_t getLSDAPointerEncoding() const { return LSDAPointerEncoding; }
201
202  void dump(raw_ostream &OS, const MCRegisterInfo *MRI,
203            bool IsEH) const override;
204
205private:
206  /// The following fields are defined in section 6.4.1 of the DWARF standard v4
207  const uint8_t Version;
208  const SmallString<8> Augmentation;
209  const uint8_t AddressSize;
210  const uint8_t SegmentDescriptorSize;
211  const uint64_t CodeAlignmentFactor;
212  const int64_t DataAlignmentFactor;
213  const uint64_t ReturnAddressRegister;
214
215  // The following are used when the CIE represents an EH frame entry.
216  const SmallString<8> AugmentationData;
217  const uint32_t FDEPointerEncoding;
218  const uint32_t LSDAPointerEncoding;
219  const Optional<uint64_t> Personality;
220  const Optional<uint32_t> PersonalityEnc;
221};
222
223/// DWARF Frame Description Entry (FDE)
224class FDE : public FrameEntry {
225public:
226  // Each FDE has a CIE it's "linked to". Our FDE contains is constructed with
227  // an offset to the CIE (provided by parsing the FDE header). The CIE itself
228  // is obtained lazily once it's actually required.
229  FDE(uint64_t Offset, uint64_t Length, int64_t LinkedCIEOffset,
230      uint64_t InitialLocation, uint64_t AddressRange, CIE *Cie,
231      Optional<uint64_t> LSDAAddress, Triple::ArchType Arch)
232      : FrameEntry(FK_FDE, Offset, Length,
233                   Cie ? Cie->getCodeAlignmentFactor() : 0,
234                   Cie ? Cie->getDataAlignmentFactor() : 0,
235                   Arch),
236        LinkedCIEOffset(LinkedCIEOffset), InitialLocation(InitialLocation),
237        AddressRange(AddressRange), LinkedCIE(Cie), LSDAAddress(LSDAAddress) {}
238
239  ~FDE() override = default;
240
241  const CIE *getLinkedCIE() const { return LinkedCIE; }
242  uint64_t getInitialLocation() const { return InitialLocation; }
243  uint64_t getAddressRange() const { return AddressRange; }
244  Optional<uint64_t> getLSDAAddress() const { return LSDAAddress; }
245
246  void dump(raw_ostream &OS, const MCRegisterInfo *MRI,
247            bool IsEH) const override;
248
249  static bool classof(const FrameEntry *FE) { return FE->getKind() == FK_FDE; }
250
251private:
252  /// The following fields are defined in section 6.4.1 of the DWARF standard v3
253  const uint64_t LinkedCIEOffset;
254  const uint64_t InitialLocation;
255  const uint64_t AddressRange;
256  const CIE *LinkedCIE;
257  const Optional<uint64_t> LSDAAddress;
258};
259
260} // end namespace dwarf
261
262/// A parsed .debug_frame or .eh_frame section
263class DWARFDebugFrame {
264  const Triple::ArchType Arch;
265  // True if this is parsing an eh_frame section.
266  const bool IsEH;
267  // Not zero for sane pointer values coming out of eh_frame
268  const uint64_t EHFrameAddress;
269
270  std::vector<std::unique_ptr<dwarf::FrameEntry>> Entries;
271  using iterator = pointee_iterator<decltype(Entries)::const_iterator>;
272
273  /// Return the entry at the given offset or nullptr.
274  dwarf::FrameEntry *getEntryAtOffset(uint64_t Offset) const;
275
276public:
277  // If IsEH is true, assume it is a .eh_frame section. Otherwise,
278  // it is a .debug_frame section. EHFrameAddress should be different
279  // than zero for correct parsing of .eh_frame addresses when they
280  // use a PC-relative encoding.
281  DWARFDebugFrame(Triple::ArchType Arch,
282                  bool IsEH = false, uint64_t EHFrameAddress = 0);
283  ~DWARFDebugFrame();
284
285  /// Dump the section data into the given stream.
286  void dump(raw_ostream &OS, const MCRegisterInfo *MRI,
287            Optional<uint64_t> Offset) const;
288
289  /// Parse the section from raw data. \p Data is assumed to contain the whole
290  /// frame section contents to be parsed.
291  void parse(DWARFDataExtractor Data);
292
293  /// Return whether the section has any entries.
294  bool empty() const { return Entries.empty(); }
295
296  /// DWARF Frame entries accessors
297  iterator begin() const { return Entries.begin(); }
298  iterator end() const { return Entries.end(); }
299  iterator_range<iterator> entries() const {
300    return iterator_range<iterator>(Entries.begin(), Entries.end());
301  }
302
303  uint64_t getEHFrameAddress() const { return EHFrameAddress; }
304};
305
306} // end namespace llvm
307
308#endif // LLVM_DEBUGINFO_DWARF_DWARFDEBUGFRAME_H
309