• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2017 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include <stdint.h>
18 
19 #include <deque>
20 #include <string>
21 #include <vector>
22 
23 #include <android-base/stringprintf.h>
24 
25 #include <unwindstack/DwarfError.h>
26 #include <unwindstack/DwarfMemory.h>
27 #include <unwindstack/Log.h>
28 #include <unwindstack/Memory.h>
29 #include <unwindstack/Regs.h>
30 
31 #include "DwarfOp.h"
32 
33 namespace unwindstack {
34 
35 template <typename AddressType>
36 constexpr typename DwarfOp<AddressType>::OpCallback DwarfOp<AddressType>::kCallbackTable[256];
37 
38 template <typename AddressType>
Eval(uint64_t start,uint64_t end)39 bool DwarfOp<AddressType>::Eval(uint64_t start, uint64_t end) {
40   is_register_ = false;
41   stack_.clear();
42   memory_->set_cur_offset(start);
43   dex_pc_set_ = false;
44 
45   // Unroll the first Decode calls to be able to check for a special
46   // sequence of ops and values that indicate this is the dex pc.
47   // The pattern is:
48   //   OP_const4u (0x0c)  'D' 'E' 'X' '1'
49   //   OP_drop (0x13)
50   if (memory_->cur_offset() < end) {
51     if (!Decode()) {
52       return false;
53     }
54   } else {
55     return true;
56   }
57   bool check_for_drop;
58   if (cur_op_ == 0x0c && operands_.back() == 0x31584544) {
59     check_for_drop = true;
60   } else {
61     check_for_drop = false;
62   }
63   if (memory_->cur_offset() < end) {
64     if (!Decode()) {
65       return false;
66     }
67   } else {
68     return true;
69   }
70 
71   if (check_for_drop && cur_op_ == 0x13) {
72     dex_pc_set_ = true;
73   }
74 
75   uint32_t iterations = 2;
76   while (memory_->cur_offset() < end) {
77     if (!Decode()) {
78       return false;
79     }
80     // To protect against a branch that creates an infinite loop,
81     // terminate if the number of iterations gets too high.
82     if (iterations++ == 1000) {
83       last_error_.code = DWARF_ERROR_TOO_MANY_ITERATIONS;
84       return false;
85     }
86   }
87   return true;
88 }
89 
90 template <typename AddressType>
Decode()91 bool DwarfOp<AddressType>::Decode() {
92   last_error_.code = DWARF_ERROR_NONE;
93   if (!memory_->ReadBytes(&cur_op_, 1)) {
94     last_error_.code = DWARF_ERROR_MEMORY_INVALID;
95     last_error_.address = memory_->cur_offset();
96     return false;
97   }
98 
99   const auto* op = &kCallbackTable[cur_op_];
100   const auto handle_func = op->handle_func;
101   if (handle_func == nullptr) {
102     last_error_.code = DWARF_ERROR_ILLEGAL_VALUE;
103     return false;
104   }
105 
106   // Make sure that the required number of stack elements is available.
107   if (stack_.size() < op->num_required_stack_values) {
108     last_error_.code = DWARF_ERROR_STACK_INDEX_NOT_VALID;
109     return false;
110   }
111 
112   operands_.clear();
113   for (size_t i = 0; i < op->num_operands; i++) {
114     uint64_t value;
115     if (!memory_->ReadEncodedValue<AddressType>(op->operands[i], &value)) {
116       last_error_.code = DWARF_ERROR_MEMORY_INVALID;
117       last_error_.address = memory_->cur_offset();
118       return false;
119     }
120     operands_.push_back(value);
121   }
122   return (this->*handle_func)();
123 }
124 
125 template <typename AddressType>
GetLogInfo(uint64_t start,uint64_t end,std::vector<std::string> * lines)126 void DwarfOp<AddressType>::GetLogInfo(uint64_t start, uint64_t end,
127                                       std::vector<std::string>* lines) {
128   memory_->set_cur_offset(start);
129   while (memory_->cur_offset() < end) {
130     uint8_t cur_op;
131     if (!memory_->ReadBytes(&cur_op, 1)) {
132       return;
133     }
134 
135     std::string raw_string(android::base::StringPrintf("Raw Data: 0x%02x", cur_op));
136     std::string log_string;
137     const auto* op = &kCallbackTable[cur_op];
138     if (op->handle_func == nullptr) {
139       log_string = "Illegal";
140     } else {
141       log_string = op->name;
142       uint64_t start_offset = memory_->cur_offset();
143       for (size_t i = 0; i < op->num_operands; i++) {
144         uint64_t value;
145         if (!memory_->ReadEncodedValue<AddressType>(op->operands[i], &value)) {
146           return;
147         }
148         log_string += ' ' + std::to_string(value);
149       }
150       uint64_t end_offset = memory_->cur_offset();
151 
152       memory_->set_cur_offset(start_offset);
153       for (size_t i = start_offset; i < end_offset; i++) {
154         uint8_t byte;
155         if (!memory_->ReadBytes(&byte, 1)) {
156           return;
157         }
158         raw_string += android::base::StringPrintf(" 0x%02x", byte);
159       }
160       memory_->set_cur_offset(end_offset);
161     }
162     lines->push_back(std::move(log_string));
163     lines->push_back(std::move(raw_string));
164   }
165 }
166 
167 template <typename AddressType>
op_deref()168 bool DwarfOp<AddressType>::op_deref() {
169   // Read the address and dereference it.
170   AddressType addr = StackPop();
171   AddressType value;
172   if (!regular_memory()->ReadFully(addr, &value, sizeof(value))) {
173     last_error_.code = DWARF_ERROR_MEMORY_INVALID;
174     last_error_.address = addr;
175     return false;
176   }
177   stack_.push_front(value);
178   return true;
179 }
180 
181 template <typename AddressType>
op_deref_size()182 bool DwarfOp<AddressType>::op_deref_size() {
183   AddressType bytes_to_read = OperandAt(0);
184   if (bytes_to_read > sizeof(AddressType) || bytes_to_read == 0) {
185     last_error_.code = DWARF_ERROR_ILLEGAL_VALUE;
186     return false;
187   }
188   // Read the address and dereference it.
189   AddressType addr = StackPop();
190   AddressType value = 0;
191   if (!regular_memory()->ReadFully(addr, &value, bytes_to_read)) {
192     last_error_.code = DWARF_ERROR_MEMORY_INVALID;
193     last_error_.address = addr;
194     return false;
195   }
196   stack_.push_front(value);
197   return true;
198 }
199 
200 template <typename AddressType>
op_push()201 bool DwarfOp<AddressType>::op_push() {
202   // Push all of the operands.
203   for (auto operand : operands_) {
204     stack_.push_front(operand);
205   }
206   return true;
207 }
208 
209 template <typename AddressType>
op_dup()210 bool DwarfOp<AddressType>::op_dup() {
211   stack_.push_front(StackAt(0));
212   return true;
213 }
214 
215 template <typename AddressType>
op_drop()216 bool DwarfOp<AddressType>::op_drop() {
217   StackPop();
218   return true;
219 }
220 
221 template <typename AddressType>
op_over()222 bool DwarfOp<AddressType>::op_over() {
223   stack_.push_front(StackAt(1));
224   return true;
225 }
226 
227 template <typename AddressType>
op_pick()228 bool DwarfOp<AddressType>::op_pick() {
229   AddressType index = OperandAt(0);
230   if (index > StackSize()) {
231     last_error_.code = DWARF_ERROR_STACK_INDEX_NOT_VALID;
232     return false;
233   }
234   stack_.push_front(StackAt(index));
235   return true;
236 }
237 
238 template <typename AddressType>
op_swap()239 bool DwarfOp<AddressType>::op_swap() {
240   AddressType old_value = stack_[0];
241   stack_[0] = stack_[1];
242   stack_[1] = old_value;
243   return true;
244 }
245 
246 template <typename AddressType>
op_rot()247 bool DwarfOp<AddressType>::op_rot() {
248   AddressType top = stack_[0];
249   stack_[0] = stack_[1];
250   stack_[1] = stack_[2];
251   stack_[2] = top;
252   return true;
253 }
254 
255 template <typename AddressType>
op_abs()256 bool DwarfOp<AddressType>::op_abs() {
257   SignedType signed_value = static_cast<SignedType>(stack_[0]);
258   if (signed_value < 0) {
259     signed_value = -signed_value;
260   }
261   stack_[0] = static_cast<AddressType>(signed_value);
262   return true;
263 }
264 
265 template <typename AddressType>
op_and()266 bool DwarfOp<AddressType>::op_and() {
267   AddressType top = StackPop();
268   stack_[0] &= top;
269   return true;
270 }
271 
272 template <typename AddressType>
op_div()273 bool DwarfOp<AddressType>::op_div() {
274   AddressType top = StackPop();
275   if (top == 0) {
276     last_error_.code = DWARF_ERROR_ILLEGAL_VALUE;
277     return false;
278   }
279   SignedType signed_divisor = static_cast<SignedType>(top);
280   SignedType signed_dividend = static_cast<SignedType>(stack_[0]);
281   stack_[0] = static_cast<AddressType>(signed_dividend / signed_divisor);
282   return true;
283 }
284 
285 template <typename AddressType>
op_minus()286 bool DwarfOp<AddressType>::op_minus() {
287   AddressType top = StackPop();
288   stack_[0] -= top;
289   return true;
290 }
291 
292 template <typename AddressType>
op_mod()293 bool DwarfOp<AddressType>::op_mod() {
294   AddressType top = StackPop();
295   if (top == 0) {
296     last_error_.code = DWARF_ERROR_ILLEGAL_VALUE;
297     return false;
298   }
299   stack_[0] %= top;
300   return true;
301 }
302 
303 template <typename AddressType>
op_mul()304 bool DwarfOp<AddressType>::op_mul() {
305   AddressType top = StackPop();
306   stack_[0] *= top;
307   return true;
308 }
309 
310 template <typename AddressType>
op_neg()311 bool DwarfOp<AddressType>::op_neg() {
312   SignedType signed_value = static_cast<SignedType>(stack_[0]);
313   stack_[0] = static_cast<AddressType>(-signed_value);
314   return true;
315 }
316 
317 template <typename AddressType>
op_not()318 bool DwarfOp<AddressType>::op_not() {
319   stack_[0] = ~stack_[0];
320   return true;
321 }
322 
323 template <typename AddressType>
op_or()324 bool DwarfOp<AddressType>::op_or() {
325   AddressType top = StackPop();
326   stack_[0] |= top;
327   return true;
328 }
329 
330 template <typename AddressType>
op_plus()331 bool DwarfOp<AddressType>::op_plus() {
332   AddressType top = StackPop();
333   stack_[0] += top;
334   return true;
335 }
336 
337 template <typename AddressType>
op_plus_uconst()338 bool DwarfOp<AddressType>::op_plus_uconst() {
339   stack_[0] += OperandAt(0);
340   return true;
341 }
342 
343 template <typename AddressType>
op_shl()344 bool DwarfOp<AddressType>::op_shl() {
345   AddressType top = StackPop();
346   stack_[0] <<= top;
347   return true;
348 }
349 
350 template <typename AddressType>
op_shr()351 bool DwarfOp<AddressType>::op_shr() {
352   AddressType top = StackPop();
353   stack_[0] >>= top;
354   return true;
355 }
356 
357 template <typename AddressType>
op_shra()358 bool DwarfOp<AddressType>::op_shra() {
359   AddressType top = StackPop();
360   SignedType signed_value = static_cast<SignedType>(stack_[0]) >> top;
361   stack_[0] = static_cast<AddressType>(signed_value);
362   return true;
363 }
364 
365 template <typename AddressType>
op_xor()366 bool DwarfOp<AddressType>::op_xor() {
367   AddressType top = StackPop();
368   stack_[0] ^= top;
369   return true;
370 }
371 
372 template <typename AddressType>
op_bra()373 bool DwarfOp<AddressType>::op_bra() {
374   // Requires one stack element.
375   AddressType top = StackPop();
376   int16_t offset = static_cast<int16_t>(OperandAt(0));
377   uint64_t cur_offset;
378   if (top != 0) {
379     cur_offset = memory_->cur_offset() + offset;
380   } else {
381     cur_offset = memory_->cur_offset() - offset;
382   }
383   memory_->set_cur_offset(cur_offset);
384   return true;
385 }
386 
387 template <typename AddressType>
op_eq()388 bool DwarfOp<AddressType>::op_eq() {
389   AddressType top = StackPop();
390   stack_[0] = bool_to_dwarf_bool(stack_[0] == top);
391   return true;
392 }
393 
394 template <typename AddressType>
op_ge()395 bool DwarfOp<AddressType>::op_ge() {
396   AddressType top = StackPop();
397   stack_[0] = bool_to_dwarf_bool(stack_[0] >= top);
398   return true;
399 }
400 
401 template <typename AddressType>
op_gt()402 bool DwarfOp<AddressType>::op_gt() {
403   AddressType top = StackPop();
404   stack_[0] = bool_to_dwarf_bool(stack_[0] > top);
405   return true;
406 }
407 
408 template <typename AddressType>
op_le()409 bool DwarfOp<AddressType>::op_le() {
410   AddressType top = StackPop();
411   stack_[0] = bool_to_dwarf_bool(stack_[0] <= top);
412   return true;
413 }
414 
415 template <typename AddressType>
op_lt()416 bool DwarfOp<AddressType>::op_lt() {
417   AddressType top = StackPop();
418   stack_[0] = bool_to_dwarf_bool(stack_[0] < top);
419   return true;
420 }
421 
422 template <typename AddressType>
op_ne()423 bool DwarfOp<AddressType>::op_ne() {
424   AddressType top = StackPop();
425   stack_[0] = bool_to_dwarf_bool(stack_[0] != top);
426   return true;
427 }
428 
429 template <typename AddressType>
op_skip()430 bool DwarfOp<AddressType>::op_skip() {
431   int16_t offset = static_cast<int16_t>(OperandAt(0));
432   uint64_t cur_offset = memory_->cur_offset() + offset;
433   memory_->set_cur_offset(cur_offset);
434   return true;
435 }
436 
437 template <typename AddressType>
op_lit()438 bool DwarfOp<AddressType>::op_lit() {
439   stack_.push_front(cur_op() - 0x30);
440   return true;
441 }
442 
443 template <typename AddressType>
op_reg()444 bool DwarfOp<AddressType>::op_reg() {
445   is_register_ = true;
446   stack_.push_front(cur_op() - 0x50);
447   return true;
448 }
449 
450 template <typename AddressType>
op_regx()451 bool DwarfOp<AddressType>::op_regx() {
452   is_register_ = true;
453   stack_.push_front(OperandAt(0));
454   return true;
455 }
456 
457 // It's not clear for breg/bregx, if this op should read the current
458 // value of the register, or where we think that register is located.
459 // For simplicity, the code will read the value before doing the unwind.
460 template <typename AddressType>
op_breg()461 bool DwarfOp<AddressType>::op_breg() {
462   uint16_t reg = cur_op() - 0x70;
463   if (reg >= regs_info_->Total()) {
464     last_error_.code = DWARF_ERROR_ILLEGAL_VALUE;
465     return false;
466   }
467   stack_.push_front(regs_info_->Get(reg) + OperandAt(0));
468   return true;
469 }
470 
471 template <typename AddressType>
op_bregx()472 bool DwarfOp<AddressType>::op_bregx() {
473   AddressType reg = OperandAt(0);
474   if (reg >= regs_info_->Total()) {
475     last_error_.code = DWARF_ERROR_ILLEGAL_VALUE;
476     return false;
477   }
478   stack_.push_front(regs_info_->Get(reg) + OperandAt(1));
479   return true;
480 }
481 
482 template <typename AddressType>
op_nop()483 bool DwarfOp<AddressType>::op_nop() {
484   return true;
485 }
486 
487 template <typename AddressType>
op_not_implemented()488 bool DwarfOp<AddressType>::op_not_implemented() {
489   last_error_.code = DWARF_ERROR_NOT_IMPLEMENTED;
490   return false;
491 }
492 
493 // Explicitly instantiate DwarfOp.
494 template class DwarfOp<uint32_t>;
495 template class DwarfOp<uint64_t>;
496 
497 }  // namespace unwindstack
498