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 <vector>
21
22namespace llvm {
23
24namespace dwarf {
25
26/// Represent a sequence of Call Frame Information instructions that, when read
27/// in order, construct a table mapping PC to frame state. This can also be
28/// referred to as "CFI rules" in DWARF literature to avoid confusion with
29/// computer programs in the broader sense, and in this context each instruction
30/// would be a rule to establish the mapping. Refer to pg. 172 in the DWARF5
31/// manual, "6.4.1 Structure of Call Frame Information".
33public:
34 static constexpr size_t MaxOperands = 3;
36
37 /// An instruction consists of a DWARF CFI opcode and an optional sequence of
38 /// operands. If it refers to an expression, then this expression has its own
39 /// sequence of operations and operands handled separately by DWARFExpression.
40 struct Instruction {
42
45 // Associated DWARF expression in case this instruction refers to one
46 std::optional<DWARFExpression> Expression;
47
49 uint32_t OperandIdx) const;
50
52 uint32_t OperandIdx) const;
53 };
54
55 using InstrList = std::vector<Instruction>;
56 using iterator = InstrList::iterator;
57 using const_iterator = InstrList::const_iterator;
58
59 iterator begin() { return Instructions.begin(); }
60 const_iterator begin() const { return Instructions.begin(); }
61 iterator end() { return Instructions.end(); }
62 const_iterator end() const { return Instructions.end(); }
63
64 unsigned size() const { return (unsigned)Instructions.size(); }
65 bool empty() const { return Instructions.empty(); }
66 uint64_t codeAlign() const { return CodeAlignmentFactor; }
67 int64_t dataAlign() const { return DataAlignmentFactor; }
68 Triple::ArchType triple() const { return Arch; }
69
70 CFIProgram(uint64_t CodeAlignmentFactor, int64_t DataAlignmentFactor,
72 : CodeAlignmentFactor(CodeAlignmentFactor),
73 DataAlignmentFactor(DataAlignmentFactor), Arch(Arch) {}
74
75 /// Parse and store a sequence of CFI instructions from Data,
76 /// starting at *Offset and ending at EndOffset. *Offset is updated
77 /// to EndOffset upon successful parsing, or indicates the offset
78 /// where a problem occurred in case an error is returned.
79 template <typename T>
81 uint64_t EndOffset) {
82 // See DWARF standard v3, section 7.23
83 const uint8_t DWARF_CFI_PRIMARY_OPCODE_MASK = 0xc0;
84 const uint8_t DWARF_CFI_PRIMARY_OPERAND_MASK = 0x3f;
85
87 while (C && C.tell() < EndOffset) {
88 uint8_t Opcode = Data.getRelocatedValue(C, 1);
89 if (!C)
90 break;
91
92 // Some instructions have a primary opcode encoded in the top bits.
93 if (uint8_t Primary = Opcode & DWARF_CFI_PRIMARY_OPCODE_MASK) {
94 // If it's a primary opcode, the first operand is encoded in the
95 // bottom bits of the opcode itself.
96 uint64_t Op1 = Opcode & DWARF_CFI_PRIMARY_OPERAND_MASK;
97 switch (Primary) {
98 case DW_CFA_advance_loc:
99 case DW_CFA_restore:
100 addInstruction(Primary, Op1);
101 break;
102 case DW_CFA_offset:
103 addInstruction(Primary, Op1, Data.getULEB128(C));
104 break;
105 default:
106 llvm_unreachable("invalid primary CFI opcode");
107 }
108 continue;
109 }
110
111 // Extended opcode - its value is Opcode itself.
112 switch (Opcode) {
113 default:
115 "invalid extended CFI opcode 0x%" PRIx8,
116 Opcode);
117 case DW_CFA_nop:
118 case DW_CFA_remember_state:
119 case DW_CFA_restore_state:
120 case DW_CFA_GNU_window_save:
121 case DW_CFA_AARCH64_negate_ra_state_with_pc:
122 // No operands
123 addInstruction(Opcode);
124 break;
125 case DW_CFA_set_loc:
126 // Operands: Address
127 addInstruction(Opcode, Data.getRelocatedAddress(C));
128 break;
129 case DW_CFA_advance_loc1:
130 // Operands: 1-byte delta
131 addInstruction(Opcode, Data.getRelocatedValue(C, 1));
132 break;
133 case DW_CFA_advance_loc2:
134 // Operands: 2-byte delta
135 addInstruction(Opcode, Data.getRelocatedValue(C, 2));
136 break;
137 case DW_CFA_advance_loc4:
138 // Operands: 4-byte delta
139 addInstruction(Opcode, Data.getRelocatedValue(C, 4));
140 break;
141 case DW_CFA_restore_extended:
142 case DW_CFA_undefined:
143 case DW_CFA_same_value:
144 case DW_CFA_def_cfa_register:
145 case DW_CFA_def_cfa_offset:
146 case DW_CFA_GNU_args_size:
147 // Operands: ULEB128
148 addInstruction(Opcode, Data.getULEB128(C));
149 break;
150 case DW_CFA_def_cfa_offset_sf:
151 // Operands: SLEB128
152 addInstruction(Opcode, Data.getSLEB128(C));
153 break;
154 case DW_CFA_LLVM_def_aspace_cfa:
155 case DW_CFA_LLVM_def_aspace_cfa_sf: {
156 auto RegNum = Data.getULEB128(C);
157 auto CfaOffset = Opcode == DW_CFA_LLVM_def_aspace_cfa
158 ? Data.getULEB128(C)
159 : Data.getSLEB128(C);
160 auto AddressSpace = Data.getULEB128(C);
161 addInstruction(Opcode, RegNum, CfaOffset, AddressSpace);
162 break;
163 }
164 case DW_CFA_offset_extended:
165 case DW_CFA_register:
166 case DW_CFA_def_cfa:
167 case DW_CFA_val_offset: {
168 // Operands: ULEB128, ULEB128
169 // Note: We can not embed getULEB128 directly into function
170 // argument list. getULEB128 changes Offset and order of evaluation
171 // for arguments is unspecified.
172 uint64_t op1 = Data.getULEB128(C);
173 uint64_t op2 = Data.getULEB128(C);
174 addInstruction(Opcode, op1, op2);
175 break;
176 }
177 case DW_CFA_offset_extended_sf:
178 case DW_CFA_def_cfa_sf:
179 case DW_CFA_val_offset_sf: {
180 // Operands: ULEB128, SLEB128
181 // Note: see comment for the previous case
182 uint64_t op1 = Data.getULEB128(C);
183 uint64_t op2 = (uint64_t)Data.getSLEB128(C);
184 addInstruction(Opcode, op1, op2);
185 break;
186 }
187 case DW_CFA_def_cfa_expression: {
188 uint64_t ExprLength = Data.getULEB128(C);
189 addInstruction(Opcode, 0);
190 StringRef Expression = Data.getBytes(C, ExprLength);
191
192 DataExtractor Extractor(Expression, Data.isLittleEndian(),
193 Data.getAddressSize());
194 // Note. We do not pass the DWARF format to DWARFExpression, because
195 // DW_OP_call_ref, the only operation which depends on the format, is
196 // prohibited in call frame instructions, see sec. 6.4.2 in DWARFv5.
197 Instructions.back().Expression =
198 DWARFExpression(Extractor, Data.getAddressSize());
199 break;
200 }
201 case DW_CFA_expression:
202 case DW_CFA_val_expression: {
203 uint64_t RegNum = Data.getULEB128(C);
204 addInstruction(Opcode, RegNum, 0);
205
206 uint64_t BlockLength = Data.getULEB128(C);
207 StringRef Expression = Data.getBytes(C, BlockLength);
208 DataExtractor Extractor(Expression, Data.isLittleEndian(),
209 Data.getAddressSize());
210 // Note. We do not pass the DWARF format to DWARFExpression, because
211 // DW_OP_call_ref, the only operation which depends on the format, is
212 // prohibited in call frame instructions, see sec. 6.4.2 in DWARFv5.
213 Instructions.back().Expression =
214 DWARFExpression(Extractor, Data.getAddressSize());
215 break;
216 }
217 }
218 }
219
220 *Offset = C.tell();
221 return C.takeError();
222 }
223
224 void addInstruction(const Instruction &I) { Instructions.push_back(I); }
225
226 /// Get a DWARF CFI call frame string for the given DW_CFA opcode.
227 LLVM_ABI StringRef callFrameString(unsigned Opcode) const;
228
229 /// Types of operands to CFI instructions
230 /// In DWARF, this type is implicitly tied to a CFI instruction opcode and
231 /// thus this type doesn't need to be explicitly written to the file (this is
232 /// not a DWARF encoding). The relationship of instrs to operand types can
233 /// be obtained from getOperandTypes() and is only used to simplify
234 /// instruction printing and error messages.
247
248 /// Get the OperandType as a "const char *".
249 LLVM_ABI static const char *operandTypeString(OperandType OT);
250
251 /// Retrieve the array describing the types of operands according to the enum
252 /// above. This is indexed by opcode.
254
255 /// Convenience method to add a new instruction with the given opcode.
256 void addInstruction(uint8_t Opcode) {
257 Instructions.push_back(Instruction(Opcode));
258 }
259
260 /// Add a new single-operand instruction.
261 void addInstruction(uint8_t Opcode, uint64_t Operand1) {
262 Instructions.push_back(Instruction(Opcode));
263 Instructions.back().Ops.push_back(Operand1);
264 }
265
266 /// Add a new instruction that has two operands.
267 void addInstruction(uint8_t Opcode, uint64_t Operand1, uint64_t Operand2) {
268 Instructions.push_back(Instruction(Opcode));
269 Instructions.back().Ops.push_back(Operand1);
270 Instructions.back().Ops.push_back(Operand2);
271 }
272
273 /// Add a new instruction that has three operands.
274 void addInstruction(uint8_t Opcode, uint64_t Operand1, uint64_t Operand2,
275 uint64_t Operand3) {
276 Instructions.push_back(Instruction(Opcode));
277 Instructions.back().Ops.push_back(Operand1);
278 Instructions.back().Ops.push_back(Operand2);
279 Instructions.back().Ops.push_back(Operand3);
280 }
281
282private:
283 std::vector<Instruction> Instructions;
284 const uint64_t CodeAlignmentFactor;
285 const int64_t DataAlignmentFactor;
286 Triple::ArchType Arch;
287};
288
289} // end namespace dwarf
290
291} // end namespace llvm
292
293#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:40
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:532
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