DwarfOp.cpp revision 2fcf4cf13e9aefa8c312084af12ca2d712a6ead3
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
33namespace unwindstack {
34
35template <typename AddressType>
36constexpr typename DwarfOp<AddressType>::OpCallback DwarfOp<AddressType>::kCallbackTable[256];
37
38template <typename AddressType>
39bool DwarfOp<AddressType>::Eval(uint64_t start, uint64_t end, uint8_t dwarf_version) {
40  uint32_t iterations = 0;
41  is_register_ = false;
42  stack_.clear();
43  memory_->set_cur_offset(start);
44  while (memory_->cur_offset() < end) {
45    if (!Decode(dwarf_version)) {
46      return false;
47    }
48    // To protect against a branch that creates an infinite loop,
49    // terminate if the number of iterations gets too high.
50    if (iterations++ == 1000) {
51      last_error_.code = DWARF_ERROR_TOO_MANY_ITERATIONS;
52      return false;
53    }
54  }
55  return true;
56}
57
58template <typename AddressType>
59bool DwarfOp<AddressType>::Decode(uint8_t dwarf_version) {
60  last_error_.code = DWARF_ERROR_NONE;
61  if (!memory_->ReadBytes(&cur_op_, 1)) {
62    last_error_.code = DWARF_ERROR_MEMORY_INVALID;
63    last_error_.address = memory_->cur_offset();
64    return false;
65  }
66
67  const auto* op = &kCallbackTable[cur_op_];
68  const auto handle_func = op->handle_func;
69  if (handle_func == nullptr) {
70    last_error_.code = DWARF_ERROR_ILLEGAL_VALUE;
71    return false;
72  }
73
74  // Check for an unsupported opcode.
75  if (dwarf_version < op->supported_version) {
76    last_error_.code = DWARF_ERROR_ILLEGAL_VALUE;
77    return false;
78  }
79
80  // Make sure that the required number of stack elements is available.
81  if (stack_.size() < op->num_required_stack_values) {
82    last_error_.code = DWARF_ERROR_STACK_INDEX_NOT_VALID;
83    return false;
84  }
85
86  operands_.clear();
87  for (size_t i = 0; i < op->num_operands; i++) {
88    uint64_t value;
89    if (!memory_->ReadEncodedValue<AddressType>(op->operands[i], &value)) {
90      last_error_.code = DWARF_ERROR_MEMORY_INVALID;
91      last_error_.address = memory_->cur_offset();
92      return false;
93    }
94    operands_.push_back(value);
95  }
96  return (this->*handle_func)();
97}
98
99template <typename AddressType>
100void DwarfOp<AddressType>::GetLogInfo(uint64_t start, uint64_t end,
101                                      std::vector<std::string>* lines) {
102  memory_->set_cur_offset(start);
103  while (memory_->cur_offset() < end) {
104    uint8_t cur_op;
105    if (!memory_->ReadBytes(&cur_op, 1)) {
106      return;
107    }
108
109    std::string raw_string(android::base::StringPrintf("Raw Data: 0x%02x", cur_op));
110    std::string log_string;
111    const auto* op = &kCallbackTable[cur_op];
112    if (op->handle_func == nullptr) {
113      log_string = "Illegal";
114    } else {
115      log_string = op->name;
116      uint64_t start_offset = memory_->cur_offset();
117      for (size_t i = 0; i < op->num_operands; i++) {
118        uint64_t value;
119        if (!memory_->ReadEncodedValue<AddressType>(op->operands[i], &value)) {
120          return;
121        }
122        log_string += ' ' + std::to_string(value);
123      }
124      uint64_t end_offset = memory_->cur_offset();
125
126      memory_->set_cur_offset(start_offset);
127      for (size_t i = start_offset; i < end_offset; i++) {
128        uint8_t byte;
129        if (!memory_->ReadBytes(&byte, 1)) {
130          return;
131        }
132        raw_string += android::base::StringPrintf(" 0x%02x", byte);
133      }
134      memory_->set_cur_offset(end_offset);
135    }
136    lines->push_back(std::move(log_string));
137    lines->push_back(std::move(raw_string));
138  }
139}
140
141template <typename AddressType>
142bool DwarfOp<AddressType>::op_deref() {
143  // Read the address and dereference it.
144  AddressType addr = StackPop();
145  AddressType value;
146  if (!regular_memory()->ReadFully(addr, &value, sizeof(value))) {
147    last_error_.code = DWARF_ERROR_MEMORY_INVALID;
148    last_error_.address = addr;
149    return false;
150  }
151  stack_.push_front(value);
152  return true;
153}
154
155template <typename AddressType>
156bool DwarfOp<AddressType>::op_deref_size() {
157  AddressType bytes_to_read = OperandAt(0);
158  if (bytes_to_read > sizeof(AddressType) || bytes_to_read == 0) {
159    last_error_.code = DWARF_ERROR_ILLEGAL_VALUE;
160    return false;
161  }
162  // Read the address and dereference it.
163  AddressType addr = StackPop();
164  AddressType value = 0;
165  if (!regular_memory()->ReadFully(addr, &value, bytes_to_read)) {
166    last_error_.code = DWARF_ERROR_MEMORY_INVALID;
167    last_error_.address = addr;
168    return false;
169  }
170  stack_.push_front(value);
171  return true;
172}
173
174template <typename AddressType>
175bool DwarfOp<AddressType>::op_push() {
176  // Push all of the operands.
177  for (auto operand : operands_) {
178    stack_.push_front(operand);
179  }
180  return true;
181}
182
183template <typename AddressType>
184bool DwarfOp<AddressType>::op_dup() {
185  stack_.push_front(StackAt(0));
186  return true;
187}
188
189template <typename AddressType>
190bool DwarfOp<AddressType>::op_drop() {
191  StackPop();
192  return true;
193}
194
195template <typename AddressType>
196bool DwarfOp<AddressType>::op_over() {
197  stack_.push_front(StackAt(1));
198  return true;
199}
200
201template <typename AddressType>
202bool DwarfOp<AddressType>::op_pick() {
203  AddressType index = OperandAt(0);
204  if (index > StackSize()) {
205    last_error_.code = DWARF_ERROR_STACK_INDEX_NOT_VALID;
206    return false;
207  }
208  stack_.push_front(StackAt(index));
209  return true;
210}
211
212template <typename AddressType>
213bool DwarfOp<AddressType>::op_swap() {
214  AddressType old_value = stack_[0];
215  stack_[0] = stack_[1];
216  stack_[1] = old_value;
217  return true;
218}
219
220template <typename AddressType>
221bool DwarfOp<AddressType>::op_rot() {
222  AddressType top = stack_[0];
223  stack_[0] = stack_[1];
224  stack_[1] = stack_[2];
225  stack_[2] = top;
226  return true;
227}
228
229template <typename AddressType>
230bool DwarfOp<AddressType>::op_abs() {
231  SignedType signed_value = static_cast<SignedType>(stack_[0]);
232  if (signed_value < 0) {
233    signed_value = -signed_value;
234  }
235  stack_[0] = static_cast<AddressType>(signed_value);
236  return true;
237}
238
239template <typename AddressType>
240bool DwarfOp<AddressType>::op_and() {
241  AddressType top = StackPop();
242  stack_[0] &= top;
243  return true;
244}
245
246template <typename AddressType>
247bool DwarfOp<AddressType>::op_div() {
248  AddressType top = StackPop();
249  if (top == 0) {
250    last_error_.code = DWARF_ERROR_ILLEGAL_VALUE;
251    return false;
252  }
253  SignedType signed_divisor = static_cast<SignedType>(top);
254  SignedType signed_dividend = static_cast<SignedType>(stack_[0]);
255  stack_[0] = static_cast<AddressType>(signed_dividend / signed_divisor);
256  return true;
257}
258
259template <typename AddressType>
260bool DwarfOp<AddressType>::op_minus() {
261  AddressType top = StackPop();
262  stack_[0] -= top;
263  return true;
264}
265
266template <typename AddressType>
267bool DwarfOp<AddressType>::op_mod() {
268  AddressType top = StackPop();
269  if (top == 0) {
270    last_error_.code = DWARF_ERROR_ILLEGAL_VALUE;
271    return false;
272  }
273  stack_[0] %= top;
274  return true;
275}
276
277template <typename AddressType>
278bool DwarfOp<AddressType>::op_mul() {
279  AddressType top = StackPop();
280  stack_[0] *= top;
281  return true;
282}
283
284template <typename AddressType>
285bool DwarfOp<AddressType>::op_neg() {
286  SignedType signed_value = static_cast<SignedType>(stack_[0]);
287  stack_[0] = static_cast<AddressType>(-signed_value);
288  return true;
289}
290
291template <typename AddressType>
292bool DwarfOp<AddressType>::op_not() {
293  stack_[0] = ~stack_[0];
294  return true;
295}
296
297template <typename AddressType>
298bool DwarfOp<AddressType>::op_or() {
299  AddressType top = StackPop();
300  stack_[0] |= top;
301  return true;
302}
303
304template <typename AddressType>
305bool DwarfOp<AddressType>::op_plus() {
306  AddressType top = StackPop();
307  stack_[0] += top;
308  return true;
309}
310
311template <typename AddressType>
312bool DwarfOp<AddressType>::op_plus_uconst() {
313  stack_[0] += OperandAt(0);
314  return true;
315}
316
317template <typename AddressType>
318bool DwarfOp<AddressType>::op_shl() {
319  AddressType top = StackPop();
320  stack_[0] <<= top;
321  return true;
322}
323
324template <typename AddressType>
325bool DwarfOp<AddressType>::op_shr() {
326  AddressType top = StackPop();
327  stack_[0] >>= top;
328  return true;
329}
330
331template <typename AddressType>
332bool DwarfOp<AddressType>::op_shra() {
333  AddressType top = StackPop();
334  SignedType signed_value = static_cast<SignedType>(stack_[0]) >> top;
335  stack_[0] = static_cast<AddressType>(signed_value);
336  return true;
337}
338
339template <typename AddressType>
340bool DwarfOp<AddressType>::op_xor() {
341  AddressType top = StackPop();
342  stack_[0] ^= top;
343  return true;
344}
345
346template <typename AddressType>
347bool DwarfOp<AddressType>::op_bra() {
348  // Requires one stack element.
349  AddressType top = StackPop();
350  int16_t offset = static_cast<int16_t>(OperandAt(0));
351  uint64_t cur_offset;
352  if (top != 0) {
353    cur_offset = memory_->cur_offset() + offset;
354  } else {
355    cur_offset = memory_->cur_offset() - offset;
356  }
357  memory_->set_cur_offset(cur_offset);
358  return true;
359}
360
361template <typename AddressType>
362bool DwarfOp<AddressType>::op_eq() {
363  AddressType top = StackPop();
364  stack_[0] = bool_to_dwarf_bool(stack_[0] == top);
365  return true;
366}
367
368template <typename AddressType>
369bool DwarfOp<AddressType>::op_ge() {
370  AddressType top = StackPop();
371  stack_[0] = bool_to_dwarf_bool(stack_[0] >= top);
372  return true;
373}
374
375template <typename AddressType>
376bool DwarfOp<AddressType>::op_gt() {
377  AddressType top = StackPop();
378  stack_[0] = bool_to_dwarf_bool(stack_[0] > top);
379  return true;
380}
381
382template <typename AddressType>
383bool DwarfOp<AddressType>::op_le() {
384  AddressType top = StackPop();
385  stack_[0] = bool_to_dwarf_bool(stack_[0] <= top);
386  return true;
387}
388
389template <typename AddressType>
390bool DwarfOp<AddressType>::op_lt() {
391  AddressType top = StackPop();
392  stack_[0] = bool_to_dwarf_bool(stack_[0] < top);
393  return true;
394}
395
396template <typename AddressType>
397bool DwarfOp<AddressType>::op_ne() {
398  AddressType top = StackPop();
399  stack_[0] = bool_to_dwarf_bool(stack_[0] != top);
400  return true;
401}
402
403template <typename AddressType>
404bool DwarfOp<AddressType>::op_skip() {
405  int16_t offset = static_cast<int16_t>(OperandAt(0));
406  uint64_t cur_offset = memory_->cur_offset() + offset;
407  memory_->set_cur_offset(cur_offset);
408  return true;
409}
410
411template <typename AddressType>
412bool DwarfOp<AddressType>::op_lit() {
413  stack_.push_front(cur_op() - 0x30);
414  return true;
415}
416
417template <typename AddressType>
418bool DwarfOp<AddressType>::op_reg() {
419  is_register_ = true;
420  stack_.push_front(cur_op() - 0x50);
421  return true;
422}
423
424template <typename AddressType>
425bool DwarfOp<AddressType>::op_regx() {
426  is_register_ = true;
427  stack_.push_front(OperandAt(0));
428  return true;
429}
430
431// It's not clear for breg/bregx, if this op should read the current
432// value of the register, or where we think that register is located.
433// For simplicity, the code will read the value before doing the unwind.
434template <typename AddressType>
435bool DwarfOp<AddressType>::op_breg() {
436  uint16_t reg = cur_op() - 0x70;
437  if (reg >= regs_->total_regs()) {
438    last_error_.code = DWARF_ERROR_ILLEGAL_VALUE;
439    return false;
440  }
441  stack_.push_front((*regs_)[reg] + OperandAt(0));
442  return true;
443}
444
445template <typename AddressType>
446bool DwarfOp<AddressType>::op_bregx() {
447  AddressType reg = OperandAt(0);
448  if (reg >= regs_->total_regs()) {
449    last_error_.code = DWARF_ERROR_ILLEGAL_VALUE;
450    return false;
451  }
452  stack_.push_front((*regs_)[reg] + OperandAt(1));
453  return true;
454}
455
456template <typename AddressType>
457bool DwarfOp<AddressType>::op_nop() {
458  return true;
459}
460
461template <typename AddressType>
462bool DwarfOp<AddressType>::op_not_implemented() {
463  last_error_.code = DWARF_ERROR_NOT_IMPLEMENTED;
464  return false;
465}
466
467// Explicitly instantiate DwarfOp.
468template class DwarfOp<uint32_t>;
469template class DwarfOp<uint64_t>;
470
471}  // namespace unwindstack
472