LLVM 22.0.0git
DWARFCFIProgram.h
Go to the documentation of this file.
1//===- DWARFCFIProgram.h ----------------------------------------*- C++ -*-===//
2//
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
6//
7//===----------------------------------------------------------------------===//
8
9#ifndef LLVM_DEBUGINFO_DWARF_LOWLEVEL_DWARFCFIPROGRAM_H
10#define LLVM_DEBUGINFO_DWARF_LOWLEVEL_DWARFCFIPROGRAM_H
11
12#include "llvm/ADT/ArrayRef.h"
14#include "llvm/ADT/iterator.h"
18#include "llvm/Support/Error.h"
20#include <memory>
21#include <vector>
22
23namespace llvm {
24
25namespace dwarf {
26
27/// Represent a sequence of Call Frame Information instructions that, when read
28/// in order, construct a table mapping PC to frame state. This can also be
29/// referred to as "CFI rules" in DWARF literature to avoid confusion with
30/// computer programs in the broader sense, and in this context each instruction
31/// would be a rule to establish the mapping. Refer to pg. 172 in the DWARF5
32/// manual, "6.4.1 Structure of Call Frame Information".
34public:
35 static constexpr size_t MaxOperands = 3;
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 {
43
46 // Associated DWARF expression in case this instruction refers to one
47 std::optional<DWARFExpression> Expression;
48
50 uint32_t OperandIdx) const;
51
53 uint32_t OperandIdx) const;
54 };
55
56 using InstrList = std::vector<Instruction>;
57 using iterator = InstrList::iterator;
58 using const_iterator = InstrList::const_iterator;
59
60 iterator begin() { return Instructions.begin(); }
61 const_iterator begin() const { return Instructions.begin(); }
62 iterator end() { return Instructions.end(); }
63 const_iterator end() const { return Instructions.end(); }
64
65 unsigned size() const { return (unsigned)Instructions.size(); }
66 bool empty() const { return Instructions.empty(); }
67 uint64_t codeAlign() const { return CodeAlignmentFactor; }
68 int64_t dataAlign() const { return DataAlignmentFactor; }
69 Triple::ArchType triple() const { return Arch; }
70
71 CFIProgram(uint64_t CodeAlignmentFactor, int64_t DataAlignmentFactor,
73 : CodeAlignmentFactor(CodeAlignmentFactor),
74 DataAlignmentFactor(DataAlignmentFactor), Arch(Arch) {}
75
76 /// Parse and store a sequence of CFI instructions from Data,
77 /// starting at *Offset and ending at EndOffset. *Offset is updated
78 /// to EndOffset upon successful parsing, or indicates the offset
79 /// where a problem occurred in case an error is returned.
80 template <typename T>
82 uint64_t EndOffset) {
83 // See DWARF standard v3, section 7.23
84 const uint8_t DWARF_CFI_PRIMARY_OPCODE_MASK = 0xc0;
85 const uint8_t DWARF_CFI_PRIMARY_OPERAND_MASK = 0x3f;
86
88 while (C && C.tell() < EndOffset) {
89 uint8_t Opcode = Data.getRelocatedValue(C, 1);
90 if (!C)
91 break;
92
93 // Some instructions have a primary opcode encoded in the top bits.
94 if (uint8_t Primary = Opcode & DWARF_CFI_PRIMARY_OPCODE_MASK) {
95 // If it's a primary opcode, the first operand is encoded in the
96 // bottom bits of the opcode itself.
97 uint64_t Op1 = Opcode & DWARF_CFI_PRIMARY_OPERAND_MASK;
98 switch (Primary) {
99 case DW_CFA_advance_loc:
100 case DW_CFA_restore:
101 addInstruction(Primary, Op1);
102 break;
103 case DW_CFA_offset:
104 addInstruction(Primary, Op1, Data.getULEB128(C));
105 break;
106 default:
107 llvm_unreachable("invalid primary CFI opcode");
108 }
109 continue;
110 }
111
112 // Extended opcode - its value is Opcode itself.
113 switch (Opcode) {
114 default:
116 "invalid extended CFI opcode 0x%" PRIx8,
117 Opcode);
118 case DW_CFA_nop:
119 case DW_CFA_remember_state:
120 case DW_CFA_restore_state:
121 case DW_CFA_GNU_window_save:
122 case DW_CFA_AARCH64_negate_ra_state_with_pc:
123 // No operands
124 addInstruction(Opcode);
125 break;
126 case DW_CFA_set_loc:
127 // Operands: Address
128 addInstruction(Opcode, Data.getRelocatedAddress(C));
129 break;
130 case DW_CFA_advance_loc1:
131 // Operands: 1-byte delta
132 addInstruction(Opcode, Data.getRelocatedValue(C, 1));
133 break;
134 case DW_CFA_advance_loc2:
135 // Operands: 2-byte delta
136 addInstruction(Opcode, Data.getRelocatedValue(C, 2));
137 break;
138 case DW_CFA_advance_loc4:
139 // Operands: 4-byte delta
140 addInstruction(Opcode, Data.getRelocatedValue(C, 4));
141 break;
142 case DW_CFA_restore_extended:
143 case DW_CFA_undefined:
144 case DW_CFA_same_value:
145 case DW_CFA_def_cfa_register:
146 case DW_CFA_def_cfa_offset:
147 case DW_CFA_GNU_args_size:
148 // Operands: ULEB128
149 addInstruction(Opcode, Data.getULEB128(C));
150 break;
151 case DW_CFA_def_cfa_offset_sf:
152 // Operands: SLEB128
153 addInstruction(Opcode, Data.getSLEB128(C));
154 break;
155 case DW_CFA_LLVM_def_aspace_cfa:
156 case DW_CFA_LLVM_def_aspace_cfa_sf: {
157 auto RegNum = Data.getULEB128(C);
158 auto CfaOffset = Opcode == DW_CFA_LLVM_def_aspace_cfa
159 ? Data.getULEB128(C)
160 : Data.getSLEB128(C);
161 auto AddressSpace = Data.getULEB128(C);
162 addInstruction(Opcode, RegNum, CfaOffset, AddressSpace);
163 break;
164 }
165 case DW_CFA_offset_extended:
166 case DW_CFA_register:
167 case DW_CFA_def_cfa:
168 case DW_CFA_val_offset: {
169 // Operands: ULEB128, ULEB128
170 // Note: We can not embed getULEB128 directly into function
171 // argument list. getULEB128 changes Offset and order of evaluation
172 // for arguments is unspecified.
173 uint64_t op1 = Data.getULEB128(C);
174 uint64_t op2 = Data.getULEB128(C);
175 addInstruction(Opcode, op1, op2);
176 break;
177 }
178 case DW_CFA_offset_extended_sf:
179 case DW_CFA_def_cfa_sf:
180 case DW_CFA_val_offset_sf: {
181 // Operands: ULEB128, SLEB128
182 // Note: see comment for the previous case
183 uint64_t op1 = Data.getULEB128(C);
184 uint64_t op2 = (uint64_t)Data.getSLEB128(C);
185 addInstruction(Opcode, op1, op2);
186 break;
187 }
188 case DW_CFA_def_cfa_expression: {
189 uint64_t ExprLength = Data.getULEB128(C);
190 addInstruction(Opcode, 0);
191 StringRef Expression = Data.getBytes(C, ExprLength);
192
193 DataExtractor Extractor(Expression, Data.isLittleEndian(),
194 Data.getAddressSize());
195 // Note. We do not pass the DWARF format to DWARFExpression, because
196 // DW_OP_call_ref, the only operation which depends on the format, is
197 // prohibited in call frame instructions, see sec. 6.4.2 in DWARFv5.
198 Instructions.back().Expression =
199 DWARFExpression(Extractor, Data.getAddressSize());
200 break;
201 }
202 case DW_CFA_expression:
203 case DW_CFA_val_expression: {
204 uint64_t RegNum = Data.getULEB128(C);
205 addInstruction(Opcode, RegNum, 0);
206
207 uint64_t BlockLength = Data.getULEB128(C);
208 StringRef Expression = Data.getBytes(C, BlockLength);
209 DataExtractor Extractor(Expression, Data.isLittleEndian(),
210 Data.getAddressSize());
211 // Note. We do not pass the DWARF format to DWARFExpression, because
212 // DW_OP_call_ref, the only operation which depends on the format, is
213 // prohibited in call frame instructions, see sec. 6.4.2 in DWARFv5.
214 Instructions.back().Expression =
215 DWARFExpression(Extractor, Data.getAddressSize());
216 break;
217 }
218 }
219 }
220
221 *Offset = C.tell();
222 return C.takeError();
223 }
224
225 void addInstruction(const Instruction &I) { Instructions.push_back(I); }
226
227 /// Get a DWARF CFI call frame string for the given DW_CFA opcode.
228 LLVM_ABI StringRef callFrameString(unsigned Opcode) const;
229
230 /// Types of operands to CFI instructions
231 /// In DWARF, this type is implicitly tied to a CFI instruction opcode and
232 /// thus this type doesn't need to be explicitly written to the file (this is
233 /// not a DWARF encoding). The relationship of instrs to operand types can
234 /// be obtained from getOperandTypes() and is only used to simplify
235 /// instruction printing and error messages.
248
249 /// Get the OperandType as a "const char *".
250 LLVM_ABI static const char *operandTypeString(OperandType OT);
251
252 /// Retrieve the array describing the types of operands according to the enum
253 /// above. This is indexed by opcode.
255
256 /// Convenience method to add a new instruction with the given opcode.
257 void addInstruction(uint8_t Opcode) {
258 Instructions.push_back(Instruction(Opcode));
259 }
260
261 /// Add a new single-operand instruction.
262 void addInstruction(uint8_t Opcode, uint64_t Operand1) {
263 Instructions.push_back(Instruction(Opcode));
264 Instructions.back().Ops.push_back(Operand1);
265 }
266
267 /// Add a new instruction that has two operands.
268 void addInstruction(uint8_t Opcode, uint64_t Operand1, uint64_t Operand2) {
269 Instructions.push_back(Instruction(Opcode));
270 Instructions.back().Ops.push_back(Operand1);
271 Instructions.back().Ops.push_back(Operand2);
272 }
273
274 /// Add a new instruction that has three operands.
275 void addInstruction(uint8_t Opcode, uint64_t Operand1, uint64_t Operand2,
276 uint64_t Operand3) {
277 Instructions.push_back(Instruction(Opcode));
278 Instructions.back().Ops.push_back(Operand1);
279 Instructions.back().Ops.push_back(Operand2);
280 Instructions.back().Ops.push_back(Operand3);
281 }
282
283private:
284 std::vector<Instruction> Instructions;
285 const uint64_t CodeAlignmentFactor;
286 const int64_t DataAlignmentFactor;
287 Triple::ArchType Arch;
288};
289
290} // end namespace dwarf
291
292} // end namespace llvm
293
294#endif // LLVM_DEBUGINFO_DWARF_LOWLEVEL_DWARFCFIPROGRAM_H
#define LLVM_ABI
Definition Compiler.h:213
#define I(x, y, z)
Definition MD5.cpp:57
This file defines the SmallString class.
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition ArrayRef.h:41
A DataExtractor suitable use for parsing dwarf from memory.
A class representing a position in a DataExtractor, as well as any error encountered during extractio...
Lightweight error class with error context and mandatory checking.
Definition Error.h:159
Tagged union holding either a T or a Error.
Definition Error.h:485
Class representing an expression and its matching format.
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
StringRef - Represent a constant reference to a string, i.e.
Definition StringRef.h:55
std::vector< Instruction > InstrList
const_iterator end() const
void addInstruction(uint8_t Opcode, uint64_t Operand1, uint64_t Operand2)
Add a new instruction that has two operands.
InstrList::const_iterator const_iterator
Triple::ArchType triple() const
InstrList::iterator iterator
OperandType
Types of operands to CFI instructions In DWARF, this type is implicitly tied to a CFI instruction opc...
void addInstruction(uint8_t Opcode, uint64_t Operand1, uint64_t Operand2, uint64_t Operand3)
Add a new instruction that has three operands.
uint64_t codeAlign() const
static constexpr size_t MaxOperands
Error parse(DWARFDataExtractorBase< T > &Data, uint64_t *Offset, uint64_t EndOffset)
Parse and store a sequence of CFI instructions from Data, starting at *Offset and ending at EndOffset...
static LLVM_ABI ArrayRef< OperandType[MaxOperands]> getOperandTypes()
Retrieve the array describing the types of operands according to the enum above.
SmallVector< uint64_t, MaxOperands > Operands
const_iterator begin() const
void addInstruction(const Instruction &I)
CFIProgram(uint64_t CodeAlignmentFactor, int64_t DataAlignmentFactor, Triple::ArchType Arch)
int64_t dataAlign() const
static LLVM_ABI const char * operandTypeString(OperandType OT)
Get the OperandType as a "const char *".
LLVM_ABI StringRef callFrameString(unsigned Opcode) const
Get a DWARF CFI call frame string for the given DW_CFA opcode.
void addInstruction(uint8_t Opcode, uint64_t Operand1)
Add a new single-operand instruction.
void addInstruction(uint8_t Opcode)
Convenience method to add a new instruction with the given opcode.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
@ C
The default llvm calling convention, compatible with C.
Definition CallingConv.h:34
Calculates the starting offsets for various sections within the .debug_names section.
Definition Dwarf.h:35
This is an optimization pass for GlobalISel generic memory operations.
@ Offset
Definition DWP.cpp:477
Error createStringError(std::error_code EC, char const *Fmt, const Ts &... Vals)
Create formatted StringError object.
Definition Error.h:1305
@ illegal_byte_sequence
Definition Errc.h:52
FunctionAddr VTableAddr uintptr_t uintptr_t Data
Definition InstrProf.h:189
An instruction consists of a DWARF CFI opcode and an optional sequence of operands.
std::optional< DWARFExpression > Expression
LLVM_ABI Expected< uint64_t > getOperandAsUnsigned(const CFIProgram &CFIP, uint32_t OperandIdx) const
LLVM_ABI Expected< int64_t > getOperandAsSigned(const CFIProgram &CFIP, uint32_t OperandIdx) const