blob: ff1c7fb383898731de832f9e9bf65478ab3413d0 [file] [log] [blame]
Andrew Scull5e1ddfa2018-08-14 10:06:54 +01001//===- 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
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 : 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
75private:
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.
128class FrameEntry {
129public:
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
148protected:
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)
161class CIE : public FrameEntry {
162public:
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
201private:
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)
220class FDE : public FrameEntry {
221public:
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
246private:
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
258class 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
270public:
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