Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/llvm/lib/DebugInfo/DWARF/LowLevel/DWARFExpression.cpp
213845 views
1
//===-- DWARFExpression.cpp -----------------------------------------------===//
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
#include "llvm/DebugInfo/DWARF/LowLevel/DWARFExpression.h"
10
#include "llvm/ADT/SmallString.h"
11
#include "llvm/Support/Format.h"
12
#include <cassert>
13
#include <cstdint>
14
#include <vector>
15
16
using namespace llvm;
17
using namespace dwarf;
18
19
namespace llvm {
20
21
typedef DWARFExpression::Operation Op;
22
typedef Op::Description Desc;
23
24
static std::vector<Desc> getOpDescriptions() {
25
std::vector<Desc> Descriptions;
26
Descriptions.resize(0xff);
27
Descriptions[DW_OP_addr] = Desc(Op::Dwarf2, Op::SizeAddr);
28
Descriptions[DW_OP_deref] = Desc(Op::Dwarf2);
29
Descriptions[DW_OP_const1u] = Desc(Op::Dwarf2, Op::Size1);
30
Descriptions[DW_OP_const1s] = Desc(Op::Dwarf2, Op::SignedSize1);
31
Descriptions[DW_OP_const2u] = Desc(Op::Dwarf2, Op::Size2);
32
Descriptions[DW_OP_const2s] = Desc(Op::Dwarf2, Op::SignedSize2);
33
Descriptions[DW_OP_const4u] = Desc(Op::Dwarf2, Op::Size4);
34
Descriptions[DW_OP_const4s] = Desc(Op::Dwarf2, Op::SignedSize4);
35
Descriptions[DW_OP_const8u] = Desc(Op::Dwarf2, Op::Size8);
36
Descriptions[DW_OP_const8s] = Desc(Op::Dwarf2, Op::SignedSize8);
37
Descriptions[DW_OP_constu] = Desc(Op::Dwarf2, Op::SizeLEB);
38
Descriptions[DW_OP_consts] = Desc(Op::Dwarf2, Op::SignedSizeLEB);
39
Descriptions[DW_OP_dup] = Desc(Op::Dwarf2);
40
Descriptions[DW_OP_drop] = Desc(Op::Dwarf2);
41
Descriptions[DW_OP_over] = Desc(Op::Dwarf2);
42
Descriptions[DW_OP_pick] = Desc(Op::Dwarf2, Op::Size1);
43
Descriptions[DW_OP_swap] = Desc(Op::Dwarf2);
44
Descriptions[DW_OP_rot] = Desc(Op::Dwarf2);
45
Descriptions[DW_OP_xderef] = Desc(Op::Dwarf2);
46
Descriptions[DW_OP_abs] = Desc(Op::Dwarf2);
47
Descriptions[DW_OP_and] = Desc(Op::Dwarf2);
48
Descriptions[DW_OP_div] = Desc(Op::Dwarf2);
49
Descriptions[DW_OP_minus] = Desc(Op::Dwarf2);
50
Descriptions[DW_OP_mod] = Desc(Op::Dwarf2);
51
Descriptions[DW_OP_mul] = Desc(Op::Dwarf2);
52
Descriptions[DW_OP_neg] = Desc(Op::Dwarf2);
53
Descriptions[DW_OP_not] = Desc(Op::Dwarf2);
54
Descriptions[DW_OP_or] = Desc(Op::Dwarf2);
55
Descriptions[DW_OP_plus] = Desc(Op::Dwarf2);
56
Descriptions[DW_OP_plus_uconst] = Desc(Op::Dwarf2, Op::SizeLEB);
57
Descriptions[DW_OP_shl] = Desc(Op::Dwarf2);
58
Descriptions[DW_OP_shr] = Desc(Op::Dwarf2);
59
Descriptions[DW_OP_shra] = Desc(Op::Dwarf2);
60
Descriptions[DW_OP_xor] = Desc(Op::Dwarf2);
61
Descriptions[DW_OP_bra] = Desc(Op::Dwarf2, Op::SignedSize2);
62
Descriptions[DW_OP_eq] = Desc(Op::Dwarf2);
63
Descriptions[DW_OP_ge] = Desc(Op::Dwarf2);
64
Descriptions[DW_OP_gt] = Desc(Op::Dwarf2);
65
Descriptions[DW_OP_le] = Desc(Op::Dwarf2);
66
Descriptions[DW_OP_lt] = Desc(Op::Dwarf2);
67
Descriptions[DW_OP_ne] = Desc(Op::Dwarf2);
68
Descriptions[DW_OP_skip] = Desc(Op::Dwarf2, Op::SignedSize2);
69
for (uint16_t LA = DW_OP_lit0; LA <= DW_OP_lit31; ++LA)
70
Descriptions[LA] = Desc(Op::Dwarf2);
71
for (uint16_t LA = DW_OP_reg0; LA <= DW_OP_reg31; ++LA)
72
Descriptions[LA] = Desc(Op::Dwarf2);
73
for (uint16_t LA = DW_OP_breg0; LA <= DW_OP_breg31; ++LA)
74
Descriptions[LA] = Desc(Op::Dwarf2, Op::SignedSizeLEB);
75
Descriptions[DW_OP_regx] = Desc(Op::Dwarf2, Op::SizeLEB);
76
Descriptions[DW_OP_fbreg] = Desc(Op::Dwarf2, Op::SignedSizeLEB);
77
Descriptions[DW_OP_bregx] = Desc(Op::Dwarf2, Op::SizeLEB, Op::SignedSizeLEB);
78
Descriptions[DW_OP_piece] = Desc(Op::Dwarf2, Op::SizeLEB);
79
Descriptions[DW_OP_deref_size] = Desc(Op::Dwarf2, Op::Size1);
80
Descriptions[DW_OP_xderef_size] = Desc(Op::Dwarf2, Op::Size1);
81
Descriptions[DW_OP_nop] = Desc(Op::Dwarf2);
82
Descriptions[DW_OP_push_object_address] = Desc(Op::Dwarf3);
83
Descriptions[DW_OP_call2] = Desc(Op::Dwarf3, Op::Size2);
84
Descriptions[DW_OP_call4] = Desc(Op::Dwarf3, Op::Size4);
85
Descriptions[DW_OP_call_ref] = Desc(Op::Dwarf3, Op::SizeRefAddr);
86
Descriptions[DW_OP_form_tls_address] = Desc(Op::Dwarf3);
87
Descriptions[DW_OP_call_frame_cfa] = Desc(Op::Dwarf3);
88
Descriptions[DW_OP_bit_piece] = Desc(Op::Dwarf3, Op::SizeLEB, Op::SizeLEB);
89
Descriptions[DW_OP_implicit_value] =
90
Desc(Op::Dwarf4, Op::SizeLEB, Op::SizeBlock);
91
Descriptions[DW_OP_stack_value] = Desc(Op::Dwarf4);
92
Descriptions[DW_OP_implicit_pointer] =
93
Desc(Op::Dwarf5, Op::SizeRefAddr, Op::SignedSizeLEB);
94
Descriptions[DW_OP_addrx] = Desc(Op::Dwarf5, Op::SizeLEB);
95
Descriptions[DW_OP_constx] = Desc(Op::Dwarf5, Op::SizeLEB);
96
Descriptions[DW_OP_entry_value] = Desc(Op::Dwarf5, Op::SizeLEB);
97
Descriptions[DW_OP_convert] = Desc(Op::Dwarf5, Op::BaseTypeRef);
98
Descriptions[DW_OP_regval_type] =
99
Desc(Op::Dwarf5, Op::SizeLEB, Op::BaseTypeRef);
100
Descriptions[DW_OP_WASM_location] =
101
Desc(Op::Dwarf4, Op::SizeLEB, Op::WasmLocationArg);
102
Descriptions[DW_OP_GNU_push_tls_address] = Desc(Op::Dwarf3);
103
Descriptions[DW_OP_GNU_addr_index] = Desc(Op::Dwarf4, Op::SizeLEB);
104
Descriptions[DW_OP_GNU_const_index] = Desc(Op::Dwarf4, Op::SizeLEB);
105
Descriptions[DW_OP_GNU_entry_value] = Desc(Op::Dwarf4, Op::SizeLEB);
106
Descriptions[DW_OP_GNU_implicit_pointer] =
107
Desc(Op::Dwarf4, Op::SizeRefAddr, Op::SignedSizeLEB);
108
// This Description acts as a marker that getSubOpDesc must be called
109
// to fetch the final Description for the operation. Each such final
110
// Description must share the same first SizeSubOpLEB operand.
111
Descriptions[DW_OP_LLVM_user] = Desc(Op::Dwarf5, Op::SizeSubOpLEB);
112
return Descriptions;
113
}
114
115
static Desc getDescImpl(ArrayRef<Desc> Descriptions, unsigned Opcode) {
116
// Handle possible corrupted or unsupported operation.
117
if (Opcode >= Descriptions.size())
118
return {};
119
return Descriptions[Opcode];
120
}
121
122
static Desc getOpDesc(unsigned Opcode) {
123
static std::vector<Desc> Descriptions = getOpDescriptions();
124
return getDescImpl(Descriptions, Opcode);
125
}
126
127
static std::vector<Desc> getSubOpDescriptions() {
128
static constexpr unsigned LlvmUserDescriptionsSize = 1
129
#define HANDLE_DW_OP_LLVM_USEROP(ID, NAME) +1
130
#include "llvm/BinaryFormat/Dwarf.def"
131
;
132
std::vector<Desc> Descriptions;
133
Descriptions.resize(LlvmUserDescriptionsSize);
134
Descriptions[DW_OP_LLVM_nop] = Desc(Op::Dwarf5, Op::SizeSubOpLEB);
135
return Descriptions;
136
}
137
138
static Desc getSubOpDesc(unsigned Opcode, unsigned SubOpcode) {
139
assert(Opcode == DW_OP_LLVM_user);
140
static std::vector<Desc> Descriptions = getSubOpDescriptions();
141
return getDescImpl(Descriptions, SubOpcode);
142
}
143
144
bool DWARFExpression::Operation::extract(DataExtractor Data,
145
uint8_t AddressSize, uint64_t Offset,
146
std::optional<DwarfFormat> Format) {
147
EndOffset = Offset;
148
Opcode = Data.getU8(&Offset);
149
150
Desc = getOpDesc(Opcode);
151
if (Desc.Version == Operation::DwarfNA)
152
return false;
153
154
Operands.resize(Desc.Op.size());
155
OperandEndOffsets.resize(Desc.Op.size());
156
for (unsigned Operand = 0; Operand < Desc.Op.size(); ++Operand) {
157
unsigned Size = Desc.Op[Operand];
158
unsigned Signed = Size & Operation::SignBit;
159
160
switch (Size & ~Operation::SignBit) {
161
case Operation::SizeSubOpLEB:
162
assert(Operand == 0 && "SubOp operand must be the first operand");
163
Operands[Operand] = Data.getULEB128(&Offset);
164
Desc = getSubOpDesc(Opcode, Operands[Operand]);
165
if (Desc.Version == Operation::DwarfNA)
166
return false;
167
assert(Desc.Op[Operand] == Operation::SizeSubOpLEB &&
168
"SizeSubOpLEB Description must begin with SizeSubOpLEB operand");
169
break;
170
case Operation::Size1:
171
Operands[Operand] = Data.getU8(&Offset);
172
if (Signed)
173
Operands[Operand] = (int8_t)Operands[Operand];
174
break;
175
case Operation::Size2:
176
Operands[Operand] = Data.getU16(&Offset);
177
if (Signed)
178
Operands[Operand] = (int16_t)Operands[Operand];
179
break;
180
case Operation::Size4:
181
Operands[Operand] = Data.getU32(&Offset);
182
if (Signed)
183
Operands[Operand] = (int32_t)Operands[Operand];
184
break;
185
case Operation::Size8:
186
Operands[Operand] = Data.getU64(&Offset);
187
break;
188
case Operation::SizeAddr:
189
Operands[Operand] = Data.getUnsigned(&Offset, AddressSize);
190
break;
191
case Operation::SizeRefAddr:
192
if (!Format)
193
return false;
194
Operands[Operand] =
195
Data.getUnsigned(&Offset, dwarf::getDwarfOffsetByteSize(*Format));
196
break;
197
case Operation::SizeLEB:
198
if (Signed)
199
Operands[Operand] = Data.getSLEB128(&Offset);
200
else
201
Operands[Operand] = Data.getULEB128(&Offset);
202
break;
203
case Operation::BaseTypeRef:
204
Operands[Operand] = Data.getULEB128(&Offset);
205
break;
206
case Operation::WasmLocationArg:
207
assert(Operand == 1);
208
switch (Operands[0]) {
209
case 0:
210
case 1:
211
case 2:
212
case 4:
213
Operands[Operand] = Data.getULEB128(&Offset);
214
break;
215
case 3: // global as uint32
216
Operands[Operand] = Data.getU32(&Offset);
217
break;
218
default:
219
return false; // Unknown Wasm location
220
}
221
break;
222
case Operation::SizeBlock:
223
// We need a size, so this cannot be the first operand
224
if (Operand == 0)
225
return false;
226
// Store the offset of the block as the value.
227
Operands[Operand] = Offset;
228
Offset += Operands[Operand - 1];
229
break;
230
default:
231
llvm_unreachable("Unknown DWARFExpression Op size");
232
}
233
234
OperandEndOffsets[Operand] = Offset;
235
}
236
237
EndOffset = Offset;
238
return true;
239
}
240
241
std::optional<unsigned> DWARFExpression::Operation::getSubCode() const {
242
if (!Desc.Op.size() || Desc.Op[0] != Operation::SizeSubOpLEB)
243
return std::nullopt;
244
return Operands[0];
245
}
246
247
bool DWARFExpression::operator==(const DWARFExpression &RHS) const {
248
if (AddressSize != RHS.AddressSize || Format != RHS.Format)
249
return false;
250
return Data.getData() == RHS.Data.getData();
251
}
252
253
} // namespace llvm
254
255