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
67 /// Discard the instructions decoded so far, e.g. the partial program left
68 /// behind by a parse() that failed, before decoding it again.
69 void clear() { Instructions.clear(); }
70
71 uint64_t codeAlign() const { return CodeAlignmentFactor; }
72 int64_t dataAlign() const { return DataAlignmentFactor; }
73 Triple::ArchType triple() const { return Arch; }
74
75 CFIProgram(uint64_t CodeAlignmentFactor, int64_t DataAlignmentFactor,
77 : CodeAlignmentFactor(CodeAlignmentFactor),
78 DataAlignmentFactor(DataAlignmentFactor), Arch(Arch) {}
79
80 /// Parse and store a sequence of CFI instructions from Data,
81 /// starting at *Offset and ending at EndOffset. *Offset is updated
82 /// to EndOffset upon successful parsing, or indicates the offset
83 /// where a problem occurred in case an error is returned.
84 template <typename T>
86 uint64_t EndOffset) {
87 // See DWARF standard v3, section 7.23
88 const uint8_t DWARF_CFI_PRIMARY_OPCODE_MASK = 0xc0;
89 const uint8_t DWARF_CFI_PRIMARY_OPERAND_MASK = 0x3f;
90
92 while (C && C.tell() < EndOffset) {
93 uint8_t Opcode = Data.getRelocatedValue(C, 1);
94 if (!C)
95 break;
96
97 // Some instructions have a primary opcode encoded in the top bits.
98 if (uint8_t Primary = Opcode & DWARF_CFI_PRIMARY_OPCODE_MASK) {
99 // If it's a primary opcode, the first operand is encoded in the
100 // bottom bits of the opcode itself.
101 uint64_t Op1 = Opcode & DWARF_CFI_PRIMARY_OPERAND_MASK;
102 switch (Primary) {
103 case DW_CFA_advance_loc:
104 case DW_CFA_restore:
105 addInstruction(Primary, Op1);
106 break;
107 case DW_CFA_offset:
108 addInstruction(Primary, Op1, Data.getULEB128(C));
109 break;
110 default:
111 llvm_unreachable("invalid primary CFI opcode");
112 }
113 continue;
114 }
115
116 // Extended opcode - its value is Opcode itself.
117 switch (Opcode) {
118 default:
120 "invalid extended CFI opcode 0x%" PRIx8,
121 Opcode);
122 case DW_CFA_nop:
123 case DW_CFA_remember_state:
124 case DW_CFA_restore_state:
125 case DW_CFA_GNU_window_save:
126 case DW_CFA_AARCH64_negate_ra_state_with_pc:
127 // No operands
128 addInstruction(Opcode);
129 break;
130 case DW_CFA_AARCH64_set_ra_state: {
131 uint64_t RAState = Data.getULEB128(C);
132 uint64_t FactoredOffset = static_cast<uint64_t>(Data.getSLEB128(C));
133 addInstruction(Opcode, RAState, FactoredOffset);
134 break;
135 }
136 case DW_CFA_set_loc:
137 // Operands: Address
138 addInstruction(Opcode, Data.getRelocatedAddress(C));
139 break;
140 case DW_CFA_advance_loc1:
141 // Operands: 1-byte delta
142 addInstruction(Opcode, Data.getRelocatedValue(C, 1));
143 break;
144 case DW_CFA_advance_loc2:
145 // Operands: 2-byte delta
146 addInstruction(Opcode, Data.getRelocatedValue(C, 2));
147 break;
148 case DW_CFA_advance_loc4:
149 // Operands: 4-byte delta
150 addInstruction(Opcode, Data.getRelocatedValue(C, 4));
151 break;
152 case DW_CFA_restore_extended:
153 case DW_CFA_undefined:
154 case DW_CFA_same_value:
155 case DW_CFA_def_cfa_register:
156 case DW_CFA_def_cfa_offset:
157 case DW_CFA_GNU_args_size:
158 // Operands: ULEB128
159 addInstruction(Opcode, Data.getULEB128(C));
160 break;
161 case DW_CFA_def_cfa_offset_sf:
162 // Operands: SLEB128
163 addInstruction(Opcode, Data.getSLEB128(C));
164 break;
165 case DW_CFA_LLVM_def_aspace_cfa:
166 case DW_CFA_LLVM_def_aspace_cfa_sf: {
167 auto RegNum = Data.getULEB128(C);
168 auto CfaOffset = Opcode == DW_CFA_LLVM_def_aspace_cfa
169 ? Data.getULEB128(C)
170 : Data.getSLEB128(C);
171 auto AddressSpace = Data.getULEB128(C);
172 addInstruction(Opcode, RegNum, CfaOffset, AddressSpace);
173 break;
174 }
175 case DW_CFA_offset_extended:
176 case DW_CFA_register:
177 case DW_CFA_def_cfa:
178 case DW_CFA_val_offset: {
179 // Operands: ULEB128, ULEB128
180 // Note: We can not embed getULEB128 directly into function
181 // argument list. getULEB128 changes Offset and order of evaluation
182 // for arguments is unspecified.
183 uint64_t op1 = Data.getULEB128(C);
184 uint64_t op2 = Data.getULEB128(C);
185 addInstruction(Opcode, op1, op2);
186 break;
187 }
188 case DW_CFA_offset_extended_sf:
189 case DW_CFA_def_cfa_sf:
190 case DW_CFA_val_offset_sf: {
191 // Operands: ULEB128, SLEB128
192 // Note: see comment for the previous case
193 uint64_t op1 = Data.getULEB128(C);
194 uint64_t op2 = (uint64_t)Data.getSLEB128(C);
195 addInstruction(Opcode, op1, op2);
196 break;
197 }
198 case DW_CFA_def_cfa_expression: {
199 uint64_t ExprLength = Data.getULEB128(C);
200 addInstruction(Opcode, 0);
201 StringRef Expression = Data.getBytes(C, ExprLength);
202
203 DataExtractor Extractor(Expression, Data.isLittleEndian());
204 // Note. We do not pass the DWARF format to DWARFExpression, because
205 // DW_OP_call_ref, the only operation which depends on the format, is
206 // prohibited in call frame instructions, see sec. 6.4.2 in DWARFv5.
207 Instructions.back().Expression =
208 DWARFExpression(Extractor, Data.getAddressSize());
209 break;
210 }
211 case DW_CFA_expression:
212 case DW_CFA_val_expression: {
213 uint64_t RegNum = Data.getULEB128(C);
214 addInstruction(Opcode, RegNum, 0);
215
216 uint64_t BlockLength = Data.getULEB128(C);
217 StringRef Expression = Data.getBytes(C, BlockLength);
218 DataExtractor Extractor(Expression, Data.isLittleEndian());
219 // Note. We do not pass the DWARF format to DWARFExpression, because
220 // DW_OP_call_ref, the only operation which depends on the format, is
221 // prohibited in call frame instructions, see sec. 6.4.2 in DWARFv5.
222 Instructions.back().Expression =
223 DWARFExpression(Extractor, Data.getAddressSize());
224 break;
225 }
226 }
227 }
228
229 *Offset = C.tell();
230 return C.takeError();
231 }
232
233 void addInstruction(const Instruction &I) { Instructions.push_back(I); }
234
235 /// Get a DWARF CFI call frame string for the given DW_CFA opcode.
236 LLVM_ABI StringRef callFrameString(unsigned Opcode) const;
237
238 /// Types of operands to CFI instructions
239 /// In DWARF, this type is implicitly tied to a CFI instruction opcode and
240 /// thus this type doesn't need to be explicitly written to the file (this is
241 /// not a DWARF encoding). The relationship of instrs to operand types can
242 /// be obtained from getOperandTypes() and is only used to simplify
243 /// instruction printing and error messages.
258
259 /// Get the OperandType as a "const char *".
260 LLVM_ABI static const char *operandTypeString(OperandType OT);
261
262 /// Retrieve the array describing the types of operands according to the enum
263 /// above. This is indexed by opcode.
265
266 /// Convenience method to add a new instruction with the given opcode.
267 void addInstruction(uint8_t Opcode) {
268 Instructions.push_back(Instruction(Opcode));
269 }
270
271 /// Add a new single-operand instruction.
272 void addInstruction(uint8_t Opcode, uint64_t Operand1) {
273 Instructions.push_back(Instruction(Opcode));
274 Instructions.back().Ops.push_back(Operand1);
275 }
276
277 /// Add a new instruction that has two operands.
278 void addInstruction(uint8_t Opcode, uint64_t Operand1, uint64_t Operand2) {
279 Instructions.push_back(Instruction(Opcode));
280 Instructions.back().Ops.push_back(Operand1);
281 Instructions.back().Ops.push_back(Operand2);
282 }
283
284 /// Add a new instruction that has three operands.
285 void addInstruction(uint8_t Opcode, uint64_t Operand1, uint64_t Operand2,
286 uint64_t Operand3) {
287 Instructions.push_back(Instruction(Opcode));
288 Instructions.back().Ops.push_back(Operand1);
289 Instructions.back().Ops.push_back(Operand2);
290 Instructions.back().Ops.push_back(Operand3);
291 }
292
293private:
294 std::vector<Instruction> Instructions;
295 const uint64_t CodeAlignmentFactor;
296 const int64_t DataAlignmentFactor;
297 Triple::ArchType Arch;
298};
299
300} // end namespace dwarf
301
302} // end namespace llvm
303
304#endif // LLVM_DEBUGINFO_DWARF_LOWLEVEL_DWARFCFIPROGRAM_H
unsigned uint64_t
static GCRegistry::Add< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
#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 *".
void clear()
Discard the instructions decoded so far, e.g.
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.
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:577
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