xref: /freebsd/contrib/llvm-project/llvm/lib/DebugInfo/DWARF/LowLevel/DWARFExpression.cpp (revision 700637cbb5e582861067a11aaca4d053546871d2)
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 
getOpDescriptions()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 
getDescImpl(ArrayRef<Desc> Descriptions,unsigned Opcode)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 
getOpDesc(unsigned Opcode)122 static Desc getOpDesc(unsigned Opcode) {
123   static std::vector<Desc> Descriptions = getOpDescriptions();
124   return getDescImpl(Descriptions, Opcode);
125 }
126 
getSubOpDescriptions()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 
getSubOpDesc(unsigned Opcode,unsigned SubOpcode)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 
extract(DataExtractor Data,uint8_t AddressSize,uint64_t Offset,std::optional<DwarfFormat> Format)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 
getSubCode() const241 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 
operator ==(const DWARFExpression & RHS) const247 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