]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugFrame.h
Merge clang 7.0.1 and several follow-up changes
[FreeBSD/FreeBSD.git] / contrib / llvm / include / llvm / DebugInfo / DWARF / DWARFDebugFrame.h
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"
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
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:
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       : 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.
70   Error parse(DataExtractor Data, uint32_t *Offset, uint32_t EndOffset);
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:
149   const FrameKind Kind;
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
157   CFIProgram CFIs;
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
258 class DWARFDebugFrame {
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;
265   using iterator = pointee_iterator<decltype(Entries)::const_iterator>;
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.
284   void parse(DWARFDataExtractor Data);
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(); }
292   iterator_range<iterator> entries() const {
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