1 /*
2 * Copyright (c) 2023 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "dwarf_op.h"
17 #include <cstring>
18 #include "dfx_log.h"
19
20 namespace OHOS {
21 namespace HiviewDFX {
22 namespace {
23 #undef LOG_DOMAIN
24 #undef LOG_TAG
25 #define LOG_DOMAIN 0xD002D11
26 #define LOG_TAG "DfxDwarfOp"
27 }
28
29 template <typename AddressType>
Eval(DfxRegs & regs,AddressType initStackValue,AddressType startPtr)30 AddressType DwarfOp<AddressType>::Eval(DfxRegs& regs, AddressType initStackValue, AddressType startPtr)
31 {
32 LOGU("Eval: initStackValue=%" PRIuPTR ", startPtr=%" PRIuPTR "", initStackValue, startPtr);
33 StackReset(initStackValue);
34
35 uintptr_t addr = startPtr;
36 uintptr_t length = memory_->ReadUleb128(addr);
37 uintptr_t end = addr + length;
38 while (addr < end) {
39 if (!Decode(regs, addr)) {
40 break;
41 }
42 }
43
44 if (stack_.empty()) {
45 LOGE("%s", "Eval: stack empty");
46 return 0;
47 }
48 return static_cast<AddressType>(StackPop());
49 }
50
51 template <typename AddressType>
Decode(DfxRegs & regs,uintptr_t & addr)52 bool DwarfOp<AddressType>::Decode(DfxRegs& regs, uintptr_t& addr)
53 {
54 uint8_t opcode;
55 memory_->ReadU8(addr, &opcode, true);
56 switch (opcode) {
57 case DW_OP_addr: {
58 LOGU("%s", "DW_OP_addr");
59 uintptr_t val;
60 memory_->ReadUptr(addr, &val, true);
61 OpPush(val);
62 }
63 break;
64 case DW_OP_deref:
65 LOGU("%s", "DW_OP_deref");
66 OpDeref();
67 break;
68 case DW_OP_const1u: {
69 LOGU("%s", "DW_OP_const1u");
70 uint8_t val;
71 memory_->ReadU8(addr, &val, true);
72 OpPush(val);
73 }
74 break;
75 case DW_OP_const1s: {
76 LOGU("%s", "DW_OP_const1s");
77 int8_t val;
78 memory_->ReadS8(addr, &val, true);
79 OpPush(val);
80 }
81 break;
82 case DW_OP_const2u: {
83 LOGU("%s", "DW_OP_const2u");
84 uint16_t val;
85 memory_->ReadU16(addr, &val, true);
86 OpPush(val);
87 }
88 break;
89 case DW_OP_const2s: {
90 LOGU("%s", "DW_OP_const2s");
91 int16_t val;
92 memory_->ReadS16(addr, &val, true);
93 OpPush(val);
94 }
95 break;
96 case DW_OP_const4u: {
97 LOGU("%s", "DW_OP_const4u");
98 uint32_t val;
99 memory_->ReadU32(addr, &val, true);
100 OpPush(val);
101 }
102 break;
103 case DW_OP_const4s: {
104 LOGU("%s", "DW_OP_const4s");
105 int32_t val;
106 memory_->ReadS32(addr, &val, true);
107 OpPush(val);
108 }
109 break;
110 case DW_OP_const8u: {
111 LOGU("%s", "DW_OP_const8u");
112 uint64_t val;
113 memory_->ReadU64(addr, &val, true);
114 OpPush(val);
115 }
116 break;
117 case DW_OP_const8s: {
118 LOGU("%s", "DW_OP_const8s");
119 int64_t val;
120 memory_->ReadS64(addr, &val, true);
121 OpPush(val);
122 }
123 break;
124 case DW_OP_constu:
125 LOGU("%s", "DW_OP_constu");
126 OpPush(memory_->ReadUleb128(addr));
127 break;
128 case DW_OP_consts:
129 LOGU("%s", "DW_OP_consts");
130 OpPush(memory_->ReadSleb128(addr));
131 break;
132 case DW_OP_dup:
133 LOGU("%s", "DW_OP_dup");
134 OpDup();
135 break;
136 case DW_OP_drop:
137 LOGU("%s", "DW_OP_drop");
138 OpDrop();
139 break;
140 case DW_OP_over:
141 LOGU("%s", "DW_OP_over");
142 OpOver();
143 break;
144 case DW_OP_pick:
145 LOGU("%s", "DW_OP_pick");
146 OpPick(addr);
147 break;
148 case DW_OP_swap:
149 LOGU("%s", "DW_OP_swap");
150 OpSwap();
151 break;
152 case DW_OP_rot:
153 LOGU("%s", "DW_OP_rot");
154 OpRot();
155 break;
156 case DW_OP_abs:
157 LOGU("%s", "DW_OP_abs");
158 OpAbs();
159 break;
160 case DW_OP_and:
161 LOGU("%s", "DW_OP_and");
162 OpAnd();
163 break;
164 case DW_OP_div:
165 LOGU("%s", "DW_OP_div");
166 OpDiv();
167 break;
168 case DW_OP_minus:
169 LOGU("%s", "DW_OP_minus");
170 OpMinus();
171 break;
172 case DW_OP_mod:
173 LOGU("%s", "DW_OP_mod");
174 OpMod();
175 break;
176 case DW_OP_mul:
177 LOGU("%s", "DW_OP_mul");
178 OpMul();
179 break;
180 case DW_OP_neg:
181 LOGU("%s", "DW_OP_neg");
182 OpNeg();
183 break;
184 case DW_OP_not:
185 LOGU("%s", "DW_OP_not");
186 OpNot();
187 break;
188 case DW_OP_or:
189 LOGU("%s", "DW_OP_or");
190 OpOr();
191 break;
192 case DW_OP_plus:
193 LOGU("%s", "DW_OP_plus");
194 OpPlus();
195 break;
196 case DW_OP_plus_uconst:
197 LOGU("%s", "DW_OP_plus_uconst");
198 OpPlusULEBConst(addr);
199 break;
200 case DW_OP_shl:
201 LOGU("%s", "DW_OP_shl");
202 OpShl();
203 break;
204 case DW_OP_shr:
205 LOGU("%s", "DW_OP_shr");
206 OpShr();
207 break;
208 case DW_OP_shra:
209 LOGU("%s", "DW_OP_shra");
210 OpShra();
211 break;
212 case DW_OP_xor:
213 LOGU("%s", "DW_OP_xor");
214 OpXor();
215 break;
216 case DW_OP_skip:
217 LOGU("%s", "DW_OP_skip");
218 OpSkip(addr);
219 break;
220 case DW_OP_bra:
221 LOGU("%s", "DW_OP_bra");
222 OpBra(addr);
223 break;
224 case DW_OP_eq:
225 LOGU("%s", "DW_OP_eq");
226 OpEQ();
227 break;
228 case DW_OP_ge:
229 LOGU("%s", "DW_OP_ge");
230 OpGE();
231 break;
232 case DW_OP_gt:
233 LOGU("%s", "DW_OP_gt");
234 OpGT();
235 break;
236 case DW_OP_le:
237 LOGU("%s", "DW_OP_le");
238 OpLE();
239 break;
240 case DW_OP_lt:
241 LOGU("%s", "DW_OP_lt");
242 OpLT();
243 break;
244 case DW_OP_ne:
245 LOGU("%s", "DW_OP_ne");
246 OpNE();
247 break;
248 case DW_OP_lit0:
249 case DW_OP_lit1:
250 case DW_OP_lit2:
251 case DW_OP_lit3:
252 case DW_OP_lit4:
253 case DW_OP_lit5:
254 case DW_OP_lit6:
255 case DW_OP_lit7:
256 case DW_OP_lit8:
257 case DW_OP_lit9:
258 case DW_OP_lit10:
259 case DW_OP_lit11:
260 case DW_OP_lit12:
261 case DW_OP_lit13:
262 case DW_OP_lit14:
263 case DW_OP_lit15:
264 case DW_OP_lit16:
265 case DW_OP_lit17:
266 case DW_OP_lit18:
267 case DW_OP_lit19:
268 case DW_OP_lit20:
269 case DW_OP_lit21:
270 case DW_OP_lit22:
271 case DW_OP_lit23:
272 case DW_OP_lit24:
273 case DW_OP_lit25:
274 case DW_OP_lit26:
275 case DW_OP_lit27:
276 case DW_OP_lit28:
277 case DW_OP_lit29:
278 case DW_OP_lit30:
279 case DW_OP_lit31:
280 LOGU("%s", "DW_OP_litXX");
281 OpLit(opcode);
282 break;
283 case DW_OP_reg0:
284 case DW_OP_reg1:
285 case DW_OP_reg2:
286 case DW_OP_reg3:
287 case DW_OP_reg4:
288 case DW_OP_reg5:
289 case DW_OP_reg6:
290 case DW_OP_reg7:
291 case DW_OP_reg8:
292 case DW_OP_reg9:
293 case DW_OP_reg10:
294 case DW_OP_reg11:
295 case DW_OP_reg12:
296 case DW_OP_reg13:
297 case DW_OP_reg14:
298 case DW_OP_reg15:
299 case DW_OP_reg16:
300 case DW_OP_reg17:
301 case DW_OP_reg18:
302 case DW_OP_reg19:
303 case DW_OP_reg20:
304 case DW_OP_reg21:
305 case DW_OP_reg22:
306 case DW_OP_reg23:
307 case DW_OP_reg24:
308 case DW_OP_reg25:
309 case DW_OP_reg26:
310 case DW_OP_reg27:
311 case DW_OP_reg28:
312 case DW_OP_reg29:
313 case DW_OP_reg30:
314 case DW_OP_reg31:
315 LOGU("%s", "DW_OP_regXX");
316 OpReg(opcode, regs);
317 break;
318 case DW_OP_regx:
319 LOGU("%s", "DW_OP_regx");
320 OpRegx(addr, regs);
321 break;
322 case DW_OP_breg0:
323 case DW_OP_breg1:
324 case DW_OP_breg2:
325 case DW_OP_breg3:
326 case DW_OP_breg4:
327 case DW_OP_breg5:
328 case DW_OP_breg6:
329 case DW_OP_breg7:
330 case DW_OP_breg8:
331 case DW_OP_breg9:
332 case DW_OP_breg10:
333 case DW_OP_breg11:
334 case DW_OP_breg12:
335 case DW_OP_breg13:
336 case DW_OP_breg14:
337 case DW_OP_breg15:
338 case DW_OP_breg16:
339 case DW_OP_breg17:
340 case DW_OP_breg18:
341 case DW_OP_breg19:
342 case DW_OP_breg20:
343 case DW_OP_breg21:
344 case DW_OP_breg22:
345 case DW_OP_breg23:
346 case DW_OP_breg24:
347 case DW_OP_breg25:
348 case DW_OP_breg26:
349 case DW_OP_breg27:
350 case DW_OP_breg28:
351 case DW_OP_breg29:
352 case DW_OP_breg30:
353 case DW_OP_breg31:
354 LOGU("%s", "DW_OP_bregXX");
355 OpBReg(opcode, addr, regs);
356 break;
357 case DW_OP_bregx:
358 LOGU("%s", "DW_OP_bregx");
359 OpBRegx(addr, regs);
360 break;
361 case DW_OP_deref_size:
362 LOGU("%s", "DW_OP_deref_size");
363 OpDerefSize(addr);
364 break;
365 case DW_OP_fbreg:
366 case DW_OP_piece:
367 case DW_OP_xderef:
368 case DW_OP_xderef_size:
369 case DW_OP_nop:
370 case DW_OP_push_object_address:
371 case DW_OP_call2:
372 case DW_OP_call4:
373 case DW_OP_call_ref:
374 LOGE("DWARF OpNop opcode: %x", opcode);
375 OpNop(opcode);
376 break;
377 default:
378 LOGE("DWARF Unexpected opcode: %x", opcode);
379 return false;
380 }
381 return true;
382 }
383
384 // offline unwind should support both dwarf32 and dwarf64 ?
385 template class DwarfOp<uintptr_t>;
386
387 } // namespace HiviewDFX
388 } // namespace OHOS
389