LLVM  10.0.0svn
DWARFDebugFrame.h
Go to the documentation of this file.
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"
18 #include "llvm/Support/Error.h"
19 #include <memory>
20 #include <vector>
21 
22 namespace llvm {
23 
24 class raw_ostream;
25 
26 namespace 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".
34 class CFIProgram {
35 public:
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
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.
73 
74  void dump(raw_ostream &OS, const MCRegisterInfo *MRI, bool IsEH,
75  unsigned IndentLevel = 1) const;
76 
77 private:
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.
131 class FrameEntry {
132 public:
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 
152 protected:
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 
162 };
163 
164 /// DWARF Common Information Entry (CIE)
165 class CIE : public FrameEntry {
166 public:
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 
205 private:
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)
224 class FDE : public FrameEntry {
225 public:
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 
251 private:
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
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;
272 
273  /// Return the entry at the given offset or nullptr.
274  dwarf::FrameEntry *getEntryAtOffset(uint64_t Offset) const;
275 
276 public:
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.
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.
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(); }
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
int64_t getDataAlignmentFactor() const
iterator_range< iterator > entries() const
static int getDataAlignmentFactor(MCStreamer &streamer)
Definition: MCDwarf.cpp:1244
InstrList::iterator iterator
iterator begin() const
DWARF Frame entries accessors.
InstrList::const_iterator const_iterator
static bool classof(const FrameEntry *FE)
A parsed .debug_frame or .eh_frame section.
This class represents lattice values for constants.
Definition: AllocatorList.h:23
Optional< uint64_t > getPersonalityAddress() const
FDE(uint64_t Offset, uint64_t Length, int64_t LinkedCIEOffset, uint64_t InitialLocation, uint64_t AddressRange, CIE *Cie, Optional< uint64_t > LSDAAddress, Triple::ArchType Arch)
An entry in either debug_frame or eh_frame.
uint8_t getVersion() const
uint64_t getEHFrameAddress() const
iterator end() const
uint32_t getLSDAPointerEncoding() const
uint64_t getCodeAlignmentFactor() const
Definition: BitVector.h:937
uint64_t getInitialLocation() const
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory)...
Definition: APInt.h:32
MCRegisterInfo base class - We assume that the target defines a static array of MCRegisterDesc object...
CFIProgram(uint64_t CodeAlignmentFactor, int64_t DataAlignmentFactor, Triple::ArchType Arch)
unsigned const MachineRegisterInfo * MRI
DWARF Frame Description Entry (FDE)
unsigned size() const
uint32_t getFDEPointerEncoding() const
const uint64_t Offset
Offset of this entry in the section.
uint64_t getLength() const
Represent a sequence of Call Frame Information instructions that, when read in order, construct a table mapping PC to frame state.
CIE(uint64_t Offset, uint64_t Length, uint8_t Version, SmallString< 8 > Augmentation, uint8_t AddressSize, uint8_t SegmentDescriptorSize, uint64_t CodeAlignmentFactor, int64_t DataAlignmentFactor, uint64_t ReturnAddressRegister, SmallString< 8 > AugmentationData, uint32_t FDEPointerEncoding, uint32_t LSDAPointerEncoding, Optional< uint64_t > Personality, Optional< uint32_t > PersonalityEnc, Triple::ArchType Arch)
static bool classof(const FrameEntry *FE)
void dump(raw_ostream &OS, const MCRegisterInfo *MRI, bool IsEH, unsigned IndentLevel=1) const
const CIE * getLinkedCIE() const
Optional< uint32_t > getPersonalityEncoding() const
std::vector< Instruction > InstrList
bool empty() const
Return whether the section has any entries.
A DataExtractor (typically for an in-memory copy of an object-file section) plus a relocation map for...
An iterator type that allows iterating over the pointees via some other iterator. ...
Definition: iterator.h:286
DWARF Common Information Entry (CIE)
SmallVector< uint64_t, 2 > Operands
A range adaptor for a pair of iterators.
const_iterator end() const
Error parse(DWARFDataExtractor Data, uint32_t *Offset, uint32_t EndOffset)
Parse and store a sequence of CFI instructions from Data, starting at *Offset and ending at EndOffset...
const CFIProgram & cfis() const
StringRef getAugmentationString() const
const uint64_t Length
Entry length as specified in DWARF.
FrameKind getKind() const
Optional< uint64_t > getLSDAAddress() const
An instruction consists of a DWARF CFI opcode and an optional sequence of operands.
uint64_t getOffset() const
const_iterator begin() const
FrameEntry(FrameKind K, uint64_t Offset, uint64_t Length, uint64_t CodeAlign, int64_t DataAlign, Triple::ArchType Arch)
Lightweight error class with error context and mandatory checking.
Definition: Error.h:157
Optional< DWARFExpression > Expression
This class implements an extremely fast bulk output stream that can only output to a stream...
Definition: raw_ostream.h:45
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:48
const uint64_t Version
Definition: InstrProf.h:984
uint64_t getReturnAddressRegister() const
uint64_t getAddressRange() const