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
16using namespace llvm;
17using namespace dwarf;
18
19namespace llvm {
20
21typedef DWARFExpression::Operation Op;
22typedef Op::Description Desc;
23
24static std::vector<Desc> getOpDescriptions() {
25 std::vector<Desc> Descriptions;
26 Descriptions.resize(new_size: 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
115static 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
122static Desc getOpDesc(unsigned Opcode) {
123 static std::vector<Desc> Descriptions = getOpDescriptions();
124 return getDescImpl(Descriptions, Opcode);
125}
126
127static 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(new_size: LlvmUserDescriptionsSize);
134 Descriptions[DW_OP_LLVM_nop] = Desc(Op::Dwarf5, Op::SizeSubOpLEB);
135 return Descriptions;
136}
137
138static Desc getSubOpDesc(unsigned Opcode, unsigned SubOpcode) {
139 assert(Opcode == DW_OP_LLVM_user);
140 static std::vector<Desc> Descriptions = getSubOpDescriptions();
141 return getDescImpl(Descriptions, Opcode: SubOpcode);
142}
143
144bool 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_ptr: &Offset);
149
150 Desc = getOpDesc(Opcode);
151 if (Desc.Version == Operation::DwarfNA)
152 return false;
153
154 Operands.resize(N: Desc.Op.size());
155 OperandEndOffsets.resize(N: 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_ptr: &Offset);
164 Desc = getSubOpDesc(Opcode, SubOpcode: 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_ptr: &Offset);
172 if (Signed)
173 Operands[Operand] = (int8_t)Operands[Operand];
174 break;
175 case Operation::Size2:
176 Operands[Operand] = Data.getU16(offset_ptr: &Offset);
177 if (Signed)
178 Operands[Operand] = (int16_t)Operands[Operand];
179 break;
180 case Operation::Size4:
181 Operands[Operand] = Data.getU32(offset_ptr: &Offset);
182 if (Signed)
183 Operands[Operand] = (int32_t)Operands[Operand];
184 break;
185 case Operation::Size8:
186 Operands[Operand] = Data.getU64(offset_ptr: &Offset);
187 break;
188 case Operation::SizeAddr:
189 Operands[Operand] = Data.getUnsigned(offset_ptr: &Offset, byte_size: AddressSize);
190 break;
191 case Operation::SizeRefAddr:
192 if (!Format)
193 return false;
194 Operands[Operand] =
195 Data.getUnsigned(offset_ptr: &Offset, byte_size: dwarf::getDwarfOffsetByteSize(Format: *Format));
196 break;
197 case Operation::SizeLEB:
198 if (Signed)
199 Operands[Operand] = Data.getSLEB128(OffsetPtr: &Offset);
200 else
201 Operands[Operand] = Data.getULEB128(offset_ptr: &Offset);
202 break;
203 case Operation::BaseTypeRef:
204 Operands[Operand] = Data.getULEB128(offset_ptr: &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_ptr: &Offset);
214 break;
215 case 3: // global as uint32
216 Operands[Operand] = Data.getU32(offset_ptr: &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
241std::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
247bool 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