Line data Source code
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 285 : 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 6378 : struct Instruction {
42 2895 : 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 425 : : CodeAlignmentFactor(CodeAlignmentFactor),
64 425 : 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 1449 : void addInstruction(uint8_t Opcode) {
82 1449 : Instructions.push_back(Instruction(Opcode));
83 1449 : }
84 :
85 : /// Add a new single-operand instruction.
86 937 : void addInstruction(uint8_t Opcode, uint64_t Operand1) {
87 1874 : Instructions.push_back(Instruction(Opcode));
88 937 : Instructions.back().Ops.push_back(Operand1);
89 937 : }
90 :
91 : /// Add a new instruction that has two operands.
92 509 : void addInstruction(uint8_t Opcode, uint64_t Operand1, uint64_t Operand2) {
93 1018 : Instructions.push_back(Instruction(Opcode));
94 509 : Instructions.back().Ops.push_back(Operand1);
95 509 : Instructions.back().Ops.push_back(Operand2);
96 509 : }
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 285 : : Kind(K), Offset(Offset), Length(Length), CFIs(CodeAlign, DataAlign) {}
135 :
136 285 : virtual ~FrameEntry() {}
137 :
138 0 : FrameKind getKind() const { return Kind; }
139 0 : uint64_t getOffset() const { return Offset; }
140 0 : uint64_t getLength() const { return Length; }
141 9 : const CFIProgram &cfis() const { return CFIs; }
142 425 : 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 140 : 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 140 : : 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 322 : PersonalityEnc(PersonalityEnc) {}
183 :
184 9 : static bool classof(const FrameEntry *FE) { return FE->getKind() == FK_CIE; }
185 :
186 : StringRef getAugmentationString() const { return Augmentation; }
187 0 : uint64_t getCodeAlignmentFactor() const { return CodeAlignmentFactor; }
188 0 : int64_t getDataAlignmentFactor() const { return DataAlignmentFactor; }
189 0 : uint8_t getVersion() const { return Version; }
190 0 : uint64_t getReturnAddressRegister() const { return ReturnAddressRegister; }
191 : Optional<uint64_t> getPersonalityAddress() const { return Personality; }
192 : Optional<uint32_t> getPersonalityEncoding() const { return PersonalityEnc; }
193 :
194 0 : uint32_t getFDEPointerEncoding() const { return FDEPointerEncoding; }
195 :
196 0 : 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 285 : : FrameEntry(FK_FDE, Offset, Length,
229 285 : Cie ? Cie->getCodeAlignmentFactor() : 0,
230 285 : Cie ? Cie->getDataAlignmentFactor() : 0),
231 : LinkedCIEOffset(LinkedCIEOffset), InitialLocation(InitialLocation),
232 855 : AddressRange(AddressRange), LinkedCIE(Cie), LSDAAddress(LSDAAddress) {}
233 :
234 285 : ~FDE() override = default;
235 :
236 0 : const CIE *getLinkedCIE() const { return LinkedCIE; }
237 0 : uint64_t getInitialLocation() const { return InitialLocation; }
238 0 : 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 0 : 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 142 : 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 1 : iterator begin() const { return Entries.begin(); }
291 1 : 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
|