LLVM  8.0.0svn
DWARFDebugFrame.h
Go to the documentation of this file.
1 //===- DWARFDebugFrame.h - Parsing of .debug_frame --------------*- C++ -*-===//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 
10 #ifndef LLVM_DEBUGINFO_DWARF_DWARFDEBUGFRAME_H
11 #define LLVM_DEBUGINFO_DWARF_DWARFDEBUGFRAME_H
12 
13 #include "llvm/ADT/ArrayRef.h"
14 #include "llvm/ADT/iterator.h"
15 #include "llvm/ADT/SmallString.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  : CodeAlignmentFactor(CodeAlignmentFactor),
64  DataAlignmentFactor(DataAlignmentFactor) {}
65 
66  /// Parse and store a sequence of CFI instructions from Data,
67  /// starting at *Offset and ending at EndOffset. *Offset is updated
68  /// to EndOffset upon successful parsing, or indicates the offset
69  /// where a problem occurred in case an error is returned.
71 
72  void dump(raw_ostream &OS, const MCRegisterInfo *MRI, bool IsEH,
73  unsigned IndentLevel = 1) const;
74 
75 private:
76  std::vector<Instruction> Instructions;
77  const uint64_t CodeAlignmentFactor;
78  const int64_t DataAlignmentFactor;
79 
80  /// Convenience method to add a new instruction with the given opcode.
81  void addInstruction(uint8_t Opcode) {
82  Instructions.push_back(Instruction(Opcode));
83  }
84 
85  /// Add a new single-operand instruction.
86  void addInstruction(uint8_t Opcode, uint64_t Operand1) {
87  Instructions.push_back(Instruction(Opcode));
88  Instructions.back().Ops.push_back(Operand1);
89  }
90 
91  /// Add a new instruction that has two operands.
92  void addInstruction(uint8_t Opcode, uint64_t Operand1, uint64_t Operand2) {
93  Instructions.push_back(Instruction(Opcode));
94  Instructions.back().Ops.push_back(Operand1);
95  Instructions.back().Ops.push_back(Operand2);
96  }
97 
98  /// Types of operands to CFI instructions
99  /// In DWARF, this type is implicitly tied to a CFI instruction opcode and
100  /// thus this type doesn't need to be explictly written to the file (this is
101  /// not a DWARF encoding). The relationship of instrs to operand types can
102  /// be obtained from getOperandTypes() and is only used to simplify
103  /// instruction printing.
104  enum OperandType {
105  OT_Unset,
106  OT_None,
107  OT_Address,
108  OT_Offset,
109  OT_FactoredCodeOffset,
110  OT_SignedFactDataOffset,
111  OT_UnsignedFactDataOffset,
112  OT_Register,
113  OT_Expression
114  };
115 
116  /// Retrieve the array describing the types of operands according to the enum
117  /// above. This is indexed by opcode.
118  static ArrayRef<OperandType[2]> getOperandTypes();
119 
120  /// Print \p Opcode's operand number \p OperandIdx which has value \p Operand.
121  void printOperand(raw_ostream &OS, const MCRegisterInfo *MRI, bool IsEH,
122  const Instruction &Instr, unsigned OperandIdx,
123  uint64_t Operand) const;
124 };
125 
126 /// An entry in either debug_frame or eh_frame. This entry can be a CIE or an
127 /// FDE.
128 class FrameEntry {
129 public:
130  enum FrameKind { FK_CIE, FK_FDE };
131 
132  FrameEntry(FrameKind K, uint64_t Offset, uint64_t Length, uint64_t CodeAlign,
133  int64_t DataAlign)
134  : Kind(K), Offset(Offset), Length(Length), CFIs(CodeAlign, DataAlign) {}
135 
136  virtual ~FrameEntry() {}
137 
138  FrameKind getKind() const { return Kind; }
139  uint64_t getOffset() const { return Offset; }
140  uint64_t getLength() const { return Length; }
141  const CFIProgram &cfis() const { return CFIs; }
142  CFIProgram &cfis() { return CFIs; }
143 
144  /// Dump the instructions in this CFI fragment
145  virtual void dump(raw_ostream &OS, const MCRegisterInfo *MRI,
146  bool IsEH) const = 0;
147 
148 protected:
150 
151  /// Offset of this entry in the section.
152  const uint64_t Offset;
153 
154  /// Entry length as specified in DWARF.
155  const uint64_t Length;
156 
158 };
159 
160 /// DWARF Common Information Entry (CIE)
161 class CIE : public FrameEntry {
162 public:
163  // CIEs (and FDEs) are simply container classes, so the only sensible way to
164  // create them is by providing the full parsed contents in the constructor.
165  CIE(uint64_t Offset, uint64_t Length, uint8_t Version,
166  SmallString<8> Augmentation, uint8_t AddressSize,
167  uint8_t SegmentDescriptorSize, uint64_t CodeAlignmentFactor,
168  int64_t DataAlignmentFactor, uint64_t ReturnAddressRegister,
169  SmallString<8> AugmentationData, uint32_t FDEPointerEncoding,
170  uint32_t LSDAPointerEncoding, Optional<uint64_t> Personality,
171  Optional<uint32_t> PersonalityEnc)
172  : FrameEntry(FK_CIE, Offset, Length, CodeAlignmentFactor,
173  DataAlignmentFactor),
174  Version(Version), Augmentation(std::move(Augmentation)),
175  AddressSize(AddressSize), SegmentDescriptorSize(SegmentDescriptorSize),
176  CodeAlignmentFactor(CodeAlignmentFactor),
177  DataAlignmentFactor(DataAlignmentFactor),
178  ReturnAddressRegister(ReturnAddressRegister),
179  AugmentationData(std::move(AugmentationData)),
180  FDEPointerEncoding(FDEPointerEncoding),
181  LSDAPointerEncoding(LSDAPointerEncoding), Personality(Personality),
182  PersonalityEnc(PersonalityEnc) {}
183 
184  static bool classof(const FrameEntry *FE) { return FE->getKind() == FK_CIE; }
185 
186  StringRef getAugmentationString() const { return Augmentation; }
187  uint64_t getCodeAlignmentFactor() const { return CodeAlignmentFactor; }
188  int64_t getDataAlignmentFactor() const { return DataAlignmentFactor; }
189  uint8_t getVersion() const { return Version; }
190  uint64_t getReturnAddressRegister() const { return ReturnAddressRegister; }
191  Optional<uint64_t> getPersonalityAddress() const { return Personality; }
192  Optional<uint32_t> getPersonalityEncoding() const { return PersonalityEnc; }
193 
194  uint32_t getFDEPointerEncoding() const { return FDEPointerEncoding; }
195 
196  uint32_t getLSDAPointerEncoding() const { return LSDAPointerEncoding; }
197 
198  void dump(raw_ostream &OS, const MCRegisterInfo *MRI,
199  bool IsEH) const override;
200 
201 private:
202  /// The following fields are defined in section 6.4.1 of the DWARF standard v4
203  const uint8_t Version;
204  const SmallString<8> Augmentation;
205  const uint8_t AddressSize;
206  const uint8_t SegmentDescriptorSize;
207  const uint64_t CodeAlignmentFactor;
208  const int64_t DataAlignmentFactor;
209  const uint64_t ReturnAddressRegister;
210 
211  // The following are used when the CIE represents an EH frame entry.
212  const SmallString<8> AugmentationData;
213  const uint32_t FDEPointerEncoding;
214  const uint32_t LSDAPointerEncoding;
215  const Optional<uint64_t> Personality;
216  const Optional<uint32_t> PersonalityEnc;
217 };
218 
219 /// DWARF Frame Description Entry (FDE)
220 class FDE : public FrameEntry {
221 public:
222  // Each FDE has a CIE it's "linked to". Our FDE contains is constructed with
223  // an offset to the CIE (provided by parsing the FDE header). The CIE itself
224  // is obtained lazily once it's actually required.
225  FDE(uint64_t Offset, uint64_t Length, int64_t LinkedCIEOffset,
226  uint64_t InitialLocation, uint64_t AddressRange, CIE *Cie,
227  Optional<uint64_t> LSDAAddress)
228  : FrameEntry(FK_FDE, Offset, Length,
229  Cie ? Cie->getCodeAlignmentFactor() : 0,
230  Cie ? Cie->getDataAlignmentFactor() : 0),
231  LinkedCIEOffset(LinkedCIEOffset), InitialLocation(InitialLocation),
232  AddressRange(AddressRange), LinkedCIE(Cie), LSDAAddress(LSDAAddress) {}
233 
234  ~FDE() override = default;
235 
236  const CIE *getLinkedCIE() const { return LinkedCIE; }
237  uint64_t getInitialLocation() const { return InitialLocation; }
238  uint64_t getAddressRange() const { return AddressRange; }
239  Optional<uint64_t> getLSDAAddress() const { return LSDAAddress; }
240 
241  void dump(raw_ostream &OS, const MCRegisterInfo *MRI,
242  bool IsEH) const override;
243 
244  static bool classof(const FrameEntry *FE) { return FE->getKind() == FK_FDE; }
245 
246 private:
247  /// The following fields are defined in section 6.4.1 of the DWARF standard v3
248  const uint64_t LinkedCIEOffset;
249  const uint64_t InitialLocation;
250  const uint64_t AddressRange;
251  const CIE *LinkedCIE;
252  const Optional<uint64_t> LSDAAddress;
253 };
254 
255 } // end namespace dwarf
256 
257 /// A parsed .debug_frame or .eh_frame section
259  // True if this is parsing an eh_frame section.
260  const bool IsEH;
261  // Not zero for sane pointer values coming out of eh_frame
262  const uint64_t EHFrameAddress;
263 
264  std::vector<std::unique_ptr<dwarf::FrameEntry>> Entries;
266 
267  /// Return the entry at the given offset or nullptr.
268  dwarf::FrameEntry *getEntryAtOffset(uint64_t Offset) const;
269 
270 public:
271  // If IsEH is true, assume it is a .eh_frame section. Otherwise,
272  // it is a .debug_frame section. EHFrameAddress should be different
273  // than zero for correct parsing of .eh_frame addresses when they
274  // use a PC-relative encoding.
275  DWARFDebugFrame(bool IsEH = false, uint64_t EHFrameAddress = 0);
276  ~DWARFDebugFrame();
277 
278  /// Dump the section data into the given stream.
279  void dump(raw_ostream &OS, const MCRegisterInfo *MRI,
280  Optional<uint64_t> Offset) const;
281 
282  /// Parse the section from raw data. \p Data is assumed to contain the whole
283  /// frame section contents to be parsed.
285 
286  /// Return whether the section has any entries.
287  bool empty() const { return Entries.empty(); }
288 
289  /// DWARF Frame entries accessors
290  iterator begin() const { return Entries.begin(); }
291  iterator end() const { return Entries.end(); }
293  return iterator_range<iterator>(Entries.begin(), Entries.end());
294  }
295 
296  uint64_t getEHFrameAddress() const { return EHFrameAddress; }
297 };
298 
299 } // end namespace llvm
300 
301 #endif // LLVM_DEBUGINFO_DWARF_DWARFDEBUGFRAME_H
int64_t getDataAlignmentFactor() const
iterator_range< iterator > entries() const
static int getDataAlignmentFactor(MCStreamer &streamer)
Definition: MCDwarf.cpp:1229
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.
Compute iterated dominance frontiers using a linear time algorithm.
Definition: AllocatorList.h:24
Optional< uint64_t > getPersonalityAddress() const
Error parse(DataExtractor Data, uint32_t *Offset, uint32_t EndOffset)
Parse and store a sequence of CFI instructions from Data, starting at *Offset and ending at EndOffset...
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:938
uint64_t getInitialLocation() const
CFIProgram(uint64_t CodeAlignmentFactor, int64_t DataAlignmentFactor)
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory)...
Definition: APInt.h:33
FDE(uint64_t Offset, uint64_t Length, int64_t LinkedCIEOffset, uint64_t InitialLocation, uint64_t AddressRange, CIE *Cie, Optional< uint64_t > LSDAAddress)
MCRegisterInfo base class - We assume that the target defines a static array of MCRegisterDesc object...
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.
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:289
FrameEntry(FrameKind K, uint64_t Offset, uint64_t Length, uint64_t CodeAlign, int64_t DataAlign)
DWARF Common Information Entry (CIE)
SmallVector< uint64_t, 2 > Operands
A range adaptor for a pair of iterators.
const_iterator end() const
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.
const unsigned Kind
uint64_t getOffset() const
const_iterator begin() const
Lightweight error class with error context and mandatory checking.
Definition: Error.h:158
Optional< DWARFExpression > Expression
This class implements an extremely fast bulk output stream that can only output to a stream...
Definition: raw_ostream.h:46
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)
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:49
const uint64_t Version
Definition: InstrProf.h:895
uint64_t getReturnAddressRegister() const
uint64_t getAddressRange() const