LLVM 24.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_AARCH64_set_ra_state: {
126 uint64_t RAState = Data.getULEB128(C);
127 uint64_t FactoredOffset = static_cast<uint64_t>(Data.getSLEB128(C));
128 addInstruction(Opcode, RAState, FactoredOffset);
129 break;
130 }
131 case DW_CFA_set_loc:
132 // Operands: Address
133 addInstruction(Opcode, Data.getRelocatedAddress(C));
134 break;
135 case DW_CFA_advance_loc1:
136 // Operands: 1-byte delta
137 addInstruction(Opcode, Data.getRelocatedValue(C, 1));
138 break;
139 case DW_CFA_advance_loc2:
140 // Operands: 2-byte delta
141 addInstruction(Opcode, Data.getRelocatedValue(C, 2));
142 break;
143 case DW_CFA_advance_loc4:
144 // Operands: 4-byte delta
145 addInstruction(Opcode, Data.getRelocatedValue(C, 4));
146 break;
147 case DW_CFA_restore_extended:
148 case DW_CFA_undefined:
149 case DW_CFA_same_value:
150 case DW_CFA_def_cfa_register:
151 case DW_CFA_def_cfa_offset:
152 case DW_CFA_GNU_args_size:
153 // Operands: ULEB128
154 addInstruction(Opcode, Data.getULEB128(C));
155 break;
156 case DW_CFA_def_cfa_offset_sf:
157 // Operands: SLEB128
158 addInstruction(Opcode, Data.getSLEB128(C));
159 break;
160 case DW_CFA_LLVM_def_aspace_cfa:
161 case DW_CFA_LLVM_def_aspace_cfa_sf: {
162 auto RegNum = Data.getULEB128(C);
163 auto CfaOffset = Opcode == DW_CFA_LLVM_def_aspace_cfa
164 ? Data.getULEB128(C)
165 : Data.getSLEB128(C);
166 auto AddressSpace = Data.getULEB128(C);
167 addInstruction(Opcode, RegNum, CfaOffset, AddressSpace);
168 break;
169 }
170 case DW_CFA_offset_extended:
171 case DW_CFA_register:
172 case DW_CFA_def_cfa:
173 case DW_CFA_val_offset: {
174 // Operands: ULEB128, ULEB128
175 // Note: We can not embed getULEB128 directly into function
176 // argument list. getULEB128 changes Offset and order of evaluation
177 // for arguments is unspecified.
178 uint64_t op1 = Data.getULEB128(C);
179 uint64_t op2 = Data.getULEB128(C);
180 addInstruction(Opcode, op1, op2);
181 break;
182 }
183 case DW_CFA_offset_extended_sf:
184 case DW_CFA_def_cfa_sf:
185 case DW_CFA_val_offset_sf: {
186 // Operands: ULEB128, SLEB128
187 // Note: see comment for the previous case
188 uint64_t op1 = Data.getULEB128(C);
189 uint64_t op2 = (uint64_t)Data.getSLEB128(C);
190 addInstruction(Opcode, op1, op2);
191 break;
192 }
193 case DW_CFA_def_cfa_expression: {
194 uint64_t ExprLength = Data.getULEB128(C);
195 addInstruction(Opcode, 0);
196 StringRef Expression = Data.getBytes(C, ExprLength);
197
198 DataExtractor Extractor(Expression, Data.isLittleEndian());
199 // Note. We do not pass the DWARF format to DWARFExpression, because
200 // DW_OP_call_ref, the only operation which depends on the format, is
201 // prohibited in call frame instructions, see sec. 6.4.2 in DWARFv5.
202 Instructions.back().Expression =
203 DWARFExpression(Extractor, Data.getAddressSize());
204 break;
205 }
206 case DW_CFA_expression:
207 case DW_CFA_val_expression: {
208 uint64_t RegNum = Data.getULEB128(C);
209 addInstruction(Opcode, RegNum, 0);
210
211 uint64_t BlockLength = Data.getULEB128(C);
212 StringRef Expression = Data.getBytes(C, BlockLength);
213 DataExtractor Extractor(Expression, Data.isLittleEndian());
214 // Note. We do not pass the DWARF format to DWARFExpression, because
215 // DW_OP_call_ref, the only operation which depends on the format, is
216 // prohibited in call frame instructions, see sec. 6.4.2 in DWARFv5.
217 Instructions.back().Expression =
218 DWARFExpression(Extractor, Data.getAddressSize());
219 break;
220 }
221 }
222 }
223
224 *Offset = C.tell();
225 return C.takeError();
226 }
227
228 void addInstruction(const Instruction &I) { Instructions.push_back(I); }
229
230 /// Get a DWARF CFI call frame string for the given DW_CFA opcode.
231 LLVM_ABI StringRef callFrameString(unsigned Opcode) const;
232
233 /// Types of operands to CFI instructions
234 /// In DWARF, this type is implicitly tied to a CFI instruction opcode and
235 /// thus this type doesn't need to be explicitly written to the file (this is
236 /// not a DWARF encoding). The relationship of instrs to operand types can
237 /// be obtained from getOperandTypes() and is only used to simplify
238 /// instruction printing and error messages.
253
254 /// Get the OperandType as a "const char *".
255 LLVM_ABI static const char *operandTypeString(OperandType OT);
256
257 /// Retrieve the array describing the types of operands according to the enum
258 /// above. This is indexed by opcode.
260
261 /// Convenience method to add a new instruction with the given opcode.
262 void addInstruction(uint8_t Opcode) {
263 Instructions.push_back(Instruction(Opcode));
264 }
265
266 /// Add a new single-operand instruction.
267 void addInstruction(uint8_t Opcode, uint64_t Operand1) {
268 Instructions.push_back(Instruction(Opcode));
269 Instructions.back().Ops.push_back(Operand1);
270 }
271
272 /// Add a new instruction that has two operands.
273 void addInstruction(uint8_t Opcode, uint64_t Operand1, uint64_t Operand2) {
274 Instructions.push_back(Instruction(Opcode));
275 Instructions.back().Ops.push_back(Operand1);
276 Instructions.back().Ops.push_back(Operand2);
277 }
278
279 /// Add a new instruction that has three operands.
280 void addInstruction(uint8_t Opcode, uint64_t Operand1, uint64_t Operand2,
281 uint64_t Operand3) {
282 Instructions.push_back(Instruction(Opcode));
283 Instructions.back().Ops.push_back(Operand1);
284 Instructions.back().Ops.push_back(Operand2);
285 Instructions.back().Ops.push_back(Operand3);
286 }
287
288private:
289 std::vector<Instruction> Instructions;
290 const uint64_t CodeAlignmentFactor;
291 const int64_t DataAlignmentFactor;
292 Triple::ArchType Arch;
293};
294
295} // end namespace dwarf
296
297} // end namespace llvm
298
299#endif // LLVM_DEBUGINFO_DWARF_LOWLEVEL_DWARFCFIPROGRAM_H
#define LLVM_ABI
Definition Compiler.h:215
#define I(x, y, z)
Definition MD5.cpp:57
This file defines the SmallString class.
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.
Represent a constant reference to a string, i.e.
Definition StringRef.h:56
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:578
Error createStringError(std::error_code EC, char const *Fmt, const Ts &... Vals)
Create formatted StringError object.
Definition Error.h:1321
@ illegal_byte_sequence
Definition Errc.h:52
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