blob: af87811f5d7d84ae17182baa4968a8bdf99fe857 [file] [log] [blame]
Andrew Scull5e1ddfa2018-08-14 10:06:54 +01001//===- DWARFDebugFrame.h - Parsing of .debug_frame --------------*- C++ -*-===//
2//
Andrew Walbran16937d02019-10-22 13:54:20 +01003// 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
Andrew Scull5e1ddfa2018-08-14 10:06:54 +01006//
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"
Andrew Walbran16937d02019-10-22 13:54:20 +010015#include "llvm/ADT/Triple.h"
Andrew Scull5e1ddfa2018-08-14 10:06:54 +010016#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
Andrew Walbran16937d02019-10-22 13:54:20 +010062 CFIProgram(uint64_t CodeAlignmentFactor, int64_t DataAlignmentFactor,
63 Triple::ArchType Arch)
Andrew Scull5e1ddfa2018-08-14 10:06:54 +010064 : CodeAlignmentFactor(CodeAlignmentFactor),
Andrew Walbran16937d02019-10-22 13:54:20 +010065 DataAlignmentFactor(DataAlignmentFactor),
66 Arch(Arch) {}
Andrew Scull5e1ddfa2018-08-14 10:06:54 +010067
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.
Olivier Deprezf4ef2d02021-04-20 13:36:24 +020072 Error parse(DWARFDataExtractor Data, uint64_t *Offset, uint64_t EndOffset);
Andrew Scull5e1ddfa2018-08-14 10:06:54 +010073
Olivier Deprezf4ef2d02021-04-20 13:36:24 +020074 void dump(raw_ostream &OS, DIDumpOptions DumpOpts, const MCRegisterInfo *MRI,
75 bool IsEH, unsigned IndentLevel = 1) const;
Andrew Scull5e1ddfa2018-08-14 10:06:54 +010076
77private:
78 std::vector<Instruction> Instructions;
79 const uint64_t CodeAlignmentFactor;
80 const int64_t DataAlignmentFactor;
Andrew Walbran16937d02019-10-22 13:54:20 +010081 Triple::ArchType Arch;
Andrew Scull5e1ddfa2018-08-14 10:06:54 +010082
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.
Olivier Deprezf4ef2d02021-04-20 13:36:24 +0200124 void printOperand(raw_ostream &OS, DIDumpOptions DumpOpts,
125 const MCRegisterInfo *MRI, bool IsEH,
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100126 const Instruction &Instr, unsigned OperandIdx,
127 uint64_t Operand) const;
128};
129
130/// An entry in either debug_frame or eh_frame. This entry can be a CIE or an
131/// FDE.
132class FrameEntry {
133public:
134 enum FrameKind { FK_CIE, FK_FDE };
135
Olivier Deprezf4ef2d02021-04-20 13:36:24 +0200136 FrameEntry(FrameKind K, bool IsDWARF64, uint64_t Offset, uint64_t Length,
137 uint64_t CodeAlign, int64_t DataAlign, Triple::ArchType Arch)
138 : Kind(K), IsDWARF64(IsDWARF64), Offset(Offset), Length(Length),
Andrew Walbran16937d02019-10-22 13:54:20 +0100139 CFIs(CodeAlign, DataAlign, Arch) {}
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100140
141 virtual ~FrameEntry() {}
142
143 FrameKind getKind() const { return Kind; }
144 uint64_t getOffset() const { return Offset; }
145 uint64_t getLength() const { return Length; }
146 const CFIProgram &cfis() const { return CFIs; }
147 CFIProgram &cfis() { return CFIs; }
148
149 /// Dump the instructions in this CFI fragment
Olivier Deprezf4ef2d02021-04-20 13:36:24 +0200150 virtual void dump(raw_ostream &OS, DIDumpOptions DumpOpts,
151 const MCRegisterInfo *MRI, bool IsEH) const = 0;
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100152
153protected:
154 const FrameKind Kind;
155
Olivier Deprezf4ef2d02021-04-20 13:36:24 +0200156 const bool IsDWARF64;
157
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100158 /// Offset of this entry in the section.
159 const uint64_t Offset;
160
161 /// Entry length as specified in DWARF.
162 const uint64_t Length;
163
164 CFIProgram CFIs;
165};
166
167/// DWARF Common Information Entry (CIE)
168class CIE : public FrameEntry {
169public:
170 // CIEs (and FDEs) are simply container classes, so the only sensible way to
171 // create them is by providing the full parsed contents in the constructor.
Olivier Deprezf4ef2d02021-04-20 13:36:24 +0200172 CIE(bool IsDWARF64, uint64_t Offset, uint64_t Length, uint8_t Version,
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100173 SmallString<8> Augmentation, uint8_t AddressSize,
174 uint8_t SegmentDescriptorSize, uint64_t CodeAlignmentFactor,
175 int64_t DataAlignmentFactor, uint64_t ReturnAddressRegister,
176 SmallString<8> AugmentationData, uint32_t FDEPointerEncoding,
177 uint32_t LSDAPointerEncoding, Optional<uint64_t> Personality,
Andrew Walbran16937d02019-10-22 13:54:20 +0100178 Optional<uint32_t> PersonalityEnc, Triple::ArchType Arch)
Olivier Deprezf4ef2d02021-04-20 13:36:24 +0200179 : FrameEntry(FK_CIE, IsDWARF64, Offset, Length, CodeAlignmentFactor,
Andrew Walbran16937d02019-10-22 13:54:20 +0100180 DataAlignmentFactor, Arch),
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100181 Version(Version), Augmentation(std::move(Augmentation)),
182 AddressSize(AddressSize), SegmentDescriptorSize(SegmentDescriptorSize),
183 CodeAlignmentFactor(CodeAlignmentFactor),
184 DataAlignmentFactor(DataAlignmentFactor),
185 ReturnAddressRegister(ReturnAddressRegister),
186 AugmentationData(std::move(AugmentationData)),
187 FDEPointerEncoding(FDEPointerEncoding),
188 LSDAPointerEncoding(LSDAPointerEncoding), Personality(Personality),
189 PersonalityEnc(PersonalityEnc) {}
190
191 static bool classof(const FrameEntry *FE) { return FE->getKind() == FK_CIE; }
192
193 StringRef getAugmentationString() const { return Augmentation; }
194 uint64_t getCodeAlignmentFactor() const { return CodeAlignmentFactor; }
195 int64_t getDataAlignmentFactor() const { return DataAlignmentFactor; }
196 uint8_t getVersion() const { return Version; }
197 uint64_t getReturnAddressRegister() const { return ReturnAddressRegister; }
198 Optional<uint64_t> getPersonalityAddress() const { return Personality; }
199 Optional<uint32_t> getPersonalityEncoding() const { return PersonalityEnc; }
200
201 uint32_t getFDEPointerEncoding() const { return FDEPointerEncoding; }
202
203 uint32_t getLSDAPointerEncoding() const { return LSDAPointerEncoding; }
204
Olivier Deprezf4ef2d02021-04-20 13:36:24 +0200205 void dump(raw_ostream &OS, DIDumpOptions DumpOpts, const MCRegisterInfo *MRI,
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100206 bool IsEH) const override;
207
208private:
209 /// The following fields are defined in section 6.4.1 of the DWARF standard v4
210 const uint8_t Version;
211 const SmallString<8> Augmentation;
212 const uint8_t AddressSize;
213 const uint8_t SegmentDescriptorSize;
214 const uint64_t CodeAlignmentFactor;
215 const int64_t DataAlignmentFactor;
216 const uint64_t ReturnAddressRegister;
217
218 // The following are used when the CIE represents an EH frame entry.
219 const SmallString<8> AugmentationData;
220 const uint32_t FDEPointerEncoding;
221 const uint32_t LSDAPointerEncoding;
222 const Optional<uint64_t> Personality;
223 const Optional<uint32_t> PersonalityEnc;
224};
225
226/// DWARF Frame Description Entry (FDE)
227class FDE : public FrameEntry {
228public:
Olivier Deprezf4ef2d02021-04-20 13:36:24 +0200229 FDE(bool IsDWARF64, uint64_t Offset, uint64_t Length, uint64_t CIEPointer,
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100230 uint64_t InitialLocation, uint64_t AddressRange, CIE *Cie,
Andrew Walbran16937d02019-10-22 13:54:20 +0100231 Optional<uint64_t> LSDAAddress, Triple::ArchType Arch)
Olivier Deprezf4ef2d02021-04-20 13:36:24 +0200232 : FrameEntry(FK_FDE, IsDWARF64, Offset, Length,
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100233 Cie ? Cie->getCodeAlignmentFactor() : 0,
Andrew Walbran16937d02019-10-22 13:54:20 +0100234 Cie ? Cie->getDataAlignmentFactor() : 0,
235 Arch),
Olivier Deprezf4ef2d02021-04-20 13:36:24 +0200236 CIEPointer(CIEPointer), InitialLocation(InitialLocation),
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100237 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
Olivier Deprezf4ef2d02021-04-20 13:36:24 +0200246 void dump(raw_ostream &OS, DIDumpOptions DumpOpts, const MCRegisterInfo *MRI,
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100247 bool IsEH) const override;
248
249 static bool classof(const FrameEntry *FE) { return FE->getKind() == FK_FDE; }
250
251private:
Olivier Deprezf4ef2d02021-04-20 13:36:24 +0200252 /// The following fields are defined in section 6.4.1 of the DWARFv3 standard.
253 /// Note that CIE pointers in EH FDEs, unlike DWARF FDEs, contain relative
254 /// offsets to the linked CIEs. See the following link for more info:
255 /// https://refspecs.linuxfoundation.org/LSB_5.0.0/LSB-Core-generic/LSB-Core-generic/ehframechpt.html
256 const uint64_t CIEPointer;
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100257 const uint64_t InitialLocation;
258 const uint64_t AddressRange;
259 const CIE *LinkedCIE;
260 const Optional<uint64_t> LSDAAddress;
261};
262
263} // end namespace dwarf
264
265/// A parsed .debug_frame or .eh_frame section
266class DWARFDebugFrame {
Andrew Walbran16937d02019-10-22 13:54:20 +0100267 const Triple::ArchType Arch;
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100268 // True if this is parsing an eh_frame section.
269 const bool IsEH;
270 // Not zero for sane pointer values coming out of eh_frame
271 const uint64_t EHFrameAddress;
272
273 std::vector<std::unique_ptr<dwarf::FrameEntry>> Entries;
274 using iterator = pointee_iterator<decltype(Entries)::const_iterator>;
275
276 /// Return the entry at the given offset or nullptr.
277 dwarf::FrameEntry *getEntryAtOffset(uint64_t Offset) const;
278
279public:
280 // If IsEH is true, assume it is a .eh_frame section. Otherwise,
281 // it is a .debug_frame section. EHFrameAddress should be different
282 // than zero for correct parsing of .eh_frame addresses when they
283 // use a PC-relative encoding.
Andrew Walbran16937d02019-10-22 13:54:20 +0100284 DWARFDebugFrame(Triple::ArchType Arch,
285 bool IsEH = false, uint64_t EHFrameAddress = 0);
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100286 ~DWARFDebugFrame();
287
288 /// Dump the section data into the given stream.
Olivier Deprezf4ef2d02021-04-20 13:36:24 +0200289 void dump(raw_ostream &OS, DIDumpOptions DumpOpts, const MCRegisterInfo *MRI,
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100290 Optional<uint64_t> Offset) const;
291
292 /// Parse the section from raw data. \p Data is assumed to contain the whole
293 /// frame section contents to be parsed.
Olivier Deprezf4ef2d02021-04-20 13:36:24 +0200294 Error parse(DWARFDataExtractor Data);
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100295
296 /// Return whether the section has any entries.
297 bool empty() const { return Entries.empty(); }
298
299 /// DWARF Frame entries accessors
300 iterator begin() const { return Entries.begin(); }
301 iterator end() const { return Entries.end(); }
302 iterator_range<iterator> entries() const {
303 return iterator_range<iterator>(Entries.begin(), Entries.end());
304 }
305
306 uint64_t getEHFrameAddress() const { return EHFrameAddress; }
307};
308
309} // end namespace llvm
310
311#endif // LLVM_DEBUGINFO_DWARF_DWARFDEBUGFRAME_H