1 //===- DWARFDebugFrame.h - Parsing of .debug_frame --------------*- C++ -*-===//
3 // 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
7 //===----------------------------------------------------------------------===//
9 #ifndef LLVM_DEBUGINFO_DWARF_DWARFDEBUGFRAME_H
10 #define LLVM_DEBUGINFO_DWARF_DWARFDEBUGFRAME_H
12 #include "llvm/ADT/ArrayRef.h"
13 #include "llvm/ADT/iterator.h"
14 #include "llvm/ADT/SmallString.h"
15 #include "llvm/ADT/Triple.h"
16 #include "llvm/DebugInfo/DWARF/DWARFDataExtractor.h"
17 #include "llvm/DebugInfo/DWARF/DWARFExpression.h"
18 #include "llvm/Support/Error.h"
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".
36 typedef SmallVector
<uint64_t, 2> Operands
;
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.
42 Instruction(uint8_t Opcode
) : Opcode(Opcode
) {}
46 // Associated DWARF expression in case this instruction refers to one
47 Optional
<DWARFExpression
> Expression
;
50 using InstrList
= std::vector
<Instruction
>;
51 using iterator
= InstrList::iterator
;
52 using const_iterator
= InstrList::const_iterator
;
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(); }
59 unsigned size() const { return (unsigned)Instructions
.size(); }
60 bool empty() const { return Instructions
.empty(); }
62 CFIProgram(uint64_t CodeAlignmentFactor
, int64_t DataAlignmentFactor
,
63 Triple::ArchType Arch
)
64 : CodeAlignmentFactor(CodeAlignmentFactor
),
65 DataAlignmentFactor(DataAlignmentFactor
),
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.
72 Error
parse(DWARFDataExtractor Data
, uint64_t *Offset
, uint64_t EndOffset
);
74 void dump(raw_ostream
&OS
, const MCRegisterInfo
*MRI
, bool IsEH
,
75 unsigned IndentLevel
= 1) const;
78 std::vector
<Instruction
> Instructions
;
79 const uint64_t CodeAlignmentFactor
;
80 const int64_t DataAlignmentFactor
;
81 Triple::ArchType Arch
;
83 /// Convenience method to add a new instruction with the given opcode.
84 void addInstruction(uint8_t Opcode
) {
85 Instructions
.push_back(Instruction(Opcode
));
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
);
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
);
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.
112 OT_FactoredCodeOffset
,
113 OT_SignedFactDataOffset
,
114 OT_UnsignedFactDataOffset
,
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();
123 /// Print \p Opcode's operand number \p OperandIdx which has value \p Operand.
124 void printOperand(raw_ostream
&OS
, const MCRegisterInfo
*MRI
, bool IsEH
,
125 const Instruction
&Instr
, unsigned OperandIdx
,
126 uint64_t Operand
) const;
129 /// An entry in either debug_frame or eh_frame. This entry can be a CIE or an
133 enum FrameKind
{ FK_CIE
, FK_FDE
};
135 FrameEntry(FrameKind K
, uint64_t Offset
, uint64_t Length
, uint64_t CodeAlign
,
136 int64_t DataAlign
, Triple::ArchType Arch
)
137 : Kind(K
), Offset(Offset
), Length(Length
),
138 CFIs(CodeAlign
, DataAlign
, Arch
) {}
140 virtual ~FrameEntry() {}
142 FrameKind
getKind() const { return Kind
; }
143 uint64_t getOffset() const { return Offset
; }
144 uint64_t getLength() const { return Length
; }
145 const CFIProgram
&cfis() const { return CFIs
; }
146 CFIProgram
&cfis() { return CFIs
; }
148 /// Dump the instructions in this CFI fragment
149 virtual void dump(raw_ostream
&OS
, const MCRegisterInfo
*MRI
,
150 bool IsEH
) const = 0;
153 const FrameKind Kind
;
155 /// Offset of this entry in the section.
156 const uint64_t Offset
;
158 /// Entry length as specified in DWARF.
159 const uint64_t Length
;
164 /// DWARF Common Information Entry (CIE)
165 class CIE
: public FrameEntry
{
167 // CIEs (and FDEs) are simply container classes, so the only sensible way to
168 // create them is by providing the full parsed contents in the constructor.
169 CIE(uint64_t Offset
, uint64_t Length
, uint8_t Version
,
170 SmallString
<8> Augmentation
, uint8_t AddressSize
,
171 uint8_t SegmentDescriptorSize
, uint64_t CodeAlignmentFactor
,
172 int64_t DataAlignmentFactor
, uint64_t ReturnAddressRegister
,
173 SmallString
<8> AugmentationData
, uint32_t FDEPointerEncoding
,
174 uint32_t LSDAPointerEncoding
, Optional
<uint64_t> Personality
,
175 Optional
<uint32_t> PersonalityEnc
, Triple::ArchType Arch
)
176 : FrameEntry(FK_CIE
, Offset
, Length
, CodeAlignmentFactor
,
177 DataAlignmentFactor
, Arch
),
178 Version(Version
), Augmentation(std::move(Augmentation
)),
179 AddressSize(AddressSize
), SegmentDescriptorSize(SegmentDescriptorSize
),
180 CodeAlignmentFactor(CodeAlignmentFactor
),
181 DataAlignmentFactor(DataAlignmentFactor
),
182 ReturnAddressRegister(ReturnAddressRegister
),
183 AugmentationData(std::move(AugmentationData
)),
184 FDEPointerEncoding(FDEPointerEncoding
),
185 LSDAPointerEncoding(LSDAPointerEncoding
), Personality(Personality
),
186 PersonalityEnc(PersonalityEnc
) {}
188 static bool classof(const FrameEntry
*FE
) { return FE
->getKind() == FK_CIE
; }
190 StringRef
getAugmentationString() const { return Augmentation
; }
191 uint64_t getCodeAlignmentFactor() const { return CodeAlignmentFactor
; }
192 int64_t getDataAlignmentFactor() const { return DataAlignmentFactor
; }
193 uint8_t getVersion() const { return Version
; }
194 uint64_t getReturnAddressRegister() const { return ReturnAddressRegister
; }
195 Optional
<uint64_t> getPersonalityAddress() const { return Personality
; }
196 Optional
<uint32_t> getPersonalityEncoding() const { return PersonalityEnc
; }
198 uint32_t getFDEPointerEncoding() const { return FDEPointerEncoding
; }
200 uint32_t getLSDAPointerEncoding() const { return LSDAPointerEncoding
; }
202 void dump(raw_ostream
&OS
, const MCRegisterInfo
*MRI
,
203 bool IsEH
) const override
;
206 /// The following fields are defined in section 6.4.1 of the DWARF standard v4
207 const uint8_t Version
;
208 const SmallString
<8> Augmentation
;
209 const uint8_t AddressSize
;
210 const uint8_t SegmentDescriptorSize
;
211 const uint64_t CodeAlignmentFactor
;
212 const int64_t DataAlignmentFactor
;
213 const uint64_t ReturnAddressRegister
;
215 // The following are used when the CIE represents an EH frame entry.
216 const SmallString
<8> AugmentationData
;
217 const uint32_t FDEPointerEncoding
;
218 const uint32_t LSDAPointerEncoding
;
219 const Optional
<uint64_t> Personality
;
220 const Optional
<uint32_t> PersonalityEnc
;
223 /// DWARF Frame Description Entry (FDE)
224 class FDE
: public FrameEntry
{
226 // Each FDE has a CIE it's "linked to". Our FDE contains is constructed with
227 // an offset to the CIE (provided by parsing the FDE header). The CIE itself
228 // is obtained lazily once it's actually required.
229 FDE(uint64_t Offset
, uint64_t Length
, int64_t LinkedCIEOffset
,
230 uint64_t InitialLocation
, uint64_t AddressRange
, CIE
*Cie
,
231 Optional
<uint64_t> LSDAAddress
, Triple::ArchType Arch
)
232 : FrameEntry(FK_FDE
, Offset
, Length
,
233 Cie
? Cie
->getCodeAlignmentFactor() : 0,
234 Cie
? Cie
->getDataAlignmentFactor() : 0,
236 LinkedCIEOffset(LinkedCIEOffset
), InitialLocation(InitialLocation
),
237 AddressRange(AddressRange
), LinkedCIE(Cie
), LSDAAddress(LSDAAddress
) {}
239 ~FDE() override
= default;
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
; }
246 void dump(raw_ostream
&OS
, const MCRegisterInfo
*MRI
,
247 bool IsEH
) const override
;
249 static bool classof(const FrameEntry
*FE
) { return FE
->getKind() == FK_FDE
; }
252 /// The following fields are defined in section 6.4.1 of the DWARF standard v3
253 const uint64_t LinkedCIEOffset
;
254 const uint64_t InitialLocation
;
255 const uint64_t AddressRange
;
256 const CIE
*LinkedCIE
;
257 const Optional
<uint64_t> LSDAAddress
;
260 } // end namespace dwarf
262 /// A parsed .debug_frame or .eh_frame section
263 class DWARFDebugFrame
{
264 const Triple::ArchType Arch
;
265 // True if this is parsing an eh_frame section.
267 // Not zero for sane pointer values coming out of eh_frame
268 const uint64_t EHFrameAddress
;
270 std::vector
<std::unique_ptr
<dwarf::FrameEntry
>> Entries
;
271 using iterator
= pointee_iterator
<decltype(Entries
)::const_iterator
>;
273 /// Return the entry at the given offset or nullptr.
274 dwarf::FrameEntry
*getEntryAtOffset(uint64_t Offset
) const;
277 // If IsEH is true, assume it is a .eh_frame section. Otherwise,
278 // it is a .debug_frame section. EHFrameAddress should be different
279 // than zero for correct parsing of .eh_frame addresses when they
280 // use a PC-relative encoding.
281 DWARFDebugFrame(Triple::ArchType Arch
,
282 bool IsEH
= false, uint64_t EHFrameAddress
= 0);
285 /// Dump the section data into the given stream.
286 void dump(raw_ostream
&OS
, const MCRegisterInfo
*MRI
,
287 Optional
<uint64_t> Offset
) const;
289 /// Parse the section from raw data. \p Data is assumed to contain the whole
290 /// frame section contents to be parsed.
291 void parse(DWARFDataExtractor Data
);
293 /// Return whether the section has any entries.
294 bool empty() const { return Entries
.empty(); }
296 /// DWARF Frame entries accessors
297 iterator
begin() const { return Entries
.begin(); }
298 iterator
end() const { return Entries
.end(); }
299 iterator_range
<iterator
> entries() const {
300 return iterator_range
<iterator
>(Entries
.begin(), Entries
.end());
303 uint64_t getEHFrameAddress() const { return EHFrameAddress
; }
306 } // end namespace llvm
308 #endif // LLVM_DEBUGINFO_DWARF_DWARFDEBUGFRAME_H