blob: 5bc60b9d16043e65cc70cb7ae796b841c5cdd7cf [file] [log] [blame]
Christopher Ferris55d22ef2017-04-04 10:41:31 -07001/*
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
Christopher Ferris2fcf4cf2018-01-23 17:52:23 -080025#include <unwindstack/DwarfError.h>
Christopher Ferrisd226a512017-07-14 10:37:19 -070026#include <unwindstack/DwarfMemory.h>
27#include <unwindstack/Log.h>
28#include <unwindstack/Memory.h>
29#include <unwindstack/Regs.h>
30
Christopher Ferris55d22ef2017-04-04 10:41:31 -070031#include "DwarfOp.h"
Christopher Ferrisd226a512017-07-14 10:37:19 -070032
33namespace unwindstack {
Christopher Ferris55d22ef2017-04-04 10:41:31 -070034
35template <typename AddressType>
36constexpr typename DwarfOp<AddressType>::OpCallback DwarfOp<AddressType>::kCallbackTable[256];
37
38template <typename AddressType>
Christopher Ferris559c7f22018-02-12 20:18:03 -080039bool DwarfOp<AddressType>::Eval(uint64_t start, uint64_t end) {
Christopher Ferris55d22ef2017-04-04 10:41:31 -070040 is_register_ = false;
41 stack_.clear();
42 memory_->set_cur_offset(start);
Christopher Ferris559c7f22018-02-12 20:18:03 -080043 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;
Christopher Ferris55d22ef2017-04-04 10:41:31 -070076 while (memory_->cur_offset() < end) {
Christopher Ferris559c7f22018-02-12 20:18:03 -080077 if (!Decode()) {
Christopher Ferris55d22ef2017-04-04 10:41:31 -070078 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) {
Christopher Ferris2fcf4cf2018-01-23 17:52:23 -080083 last_error_.code = DWARF_ERROR_TOO_MANY_ITERATIONS;
Christopher Ferris55d22ef2017-04-04 10:41:31 -070084 return false;
85 }
86 }
87 return true;
88}
89
90template <typename AddressType>
Christopher Ferris559c7f22018-02-12 20:18:03 -080091bool DwarfOp<AddressType>::Decode() {
Christopher Ferris2fcf4cf2018-01-23 17:52:23 -080092 last_error_.code = DWARF_ERROR_NONE;
Christopher Ferris55d22ef2017-04-04 10:41:31 -070093 if (!memory_->ReadBytes(&cur_op_, 1)) {
Christopher Ferris2fcf4cf2018-01-23 17:52:23 -080094 last_error_.code = DWARF_ERROR_MEMORY_INVALID;
95 last_error_.address = memory_->cur_offset();
Christopher Ferris55d22ef2017-04-04 10:41:31 -070096 return false;
97 }
98
99 const auto* op = &kCallbackTable[cur_op_];
100 const auto handle_func = op->handle_func;
101 if (handle_func == nullptr) {
Christopher Ferris2fcf4cf2018-01-23 17:52:23 -0800102 last_error_.code = DWARF_ERROR_ILLEGAL_VALUE;
Christopher Ferris55d22ef2017-04-04 10:41:31 -0700103 return false;
104 }
105
Christopher Ferris55d22ef2017-04-04 10:41:31 -0700106 // Make sure that the required number of stack elements is available.
107 if (stack_.size() < op->num_required_stack_values) {
Christopher Ferris2fcf4cf2018-01-23 17:52:23 -0800108 last_error_.code = DWARF_ERROR_STACK_INDEX_NOT_VALID;
Christopher Ferris55d22ef2017-04-04 10:41:31 -0700109 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)) {
Christopher Ferris2fcf4cf2018-01-23 17:52:23 -0800116 last_error_.code = DWARF_ERROR_MEMORY_INVALID;
117 last_error_.address = memory_->cur_offset();
Christopher Ferris55d22ef2017-04-04 10:41:31 -0700118 return false;
119 }
120 operands_.push_back(value);
121 }
122 return (this->*handle_func)();
123}
124
125template <typename AddressType>
126void 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
167template <typename AddressType>
168bool DwarfOp<AddressType>::op_deref() {
169 // Read the address and dereference it.
170 AddressType addr = StackPop();
171 AddressType value;
Josh Gaoef35aa52017-10-18 11:44:51 -0700172 if (!regular_memory()->ReadFully(addr, &value, sizeof(value))) {
Christopher Ferris2fcf4cf2018-01-23 17:52:23 -0800173 last_error_.code = DWARF_ERROR_MEMORY_INVALID;
174 last_error_.address = addr;
Christopher Ferris55d22ef2017-04-04 10:41:31 -0700175 return false;
176 }
177 stack_.push_front(value);
178 return true;
179}
180
181template <typename AddressType>
182bool DwarfOp<AddressType>::op_deref_size() {
183 AddressType bytes_to_read = OperandAt(0);
184 if (bytes_to_read > sizeof(AddressType) || bytes_to_read == 0) {
Christopher Ferris2fcf4cf2018-01-23 17:52:23 -0800185 last_error_.code = DWARF_ERROR_ILLEGAL_VALUE;
Christopher Ferris55d22ef2017-04-04 10:41:31 -0700186 return false;
187 }
188 // Read the address and dereference it.
189 AddressType addr = StackPop();
190 AddressType value = 0;
Josh Gaoef35aa52017-10-18 11:44:51 -0700191 if (!regular_memory()->ReadFully(addr, &value, bytes_to_read)) {
Christopher Ferris2fcf4cf2018-01-23 17:52:23 -0800192 last_error_.code = DWARF_ERROR_MEMORY_INVALID;
193 last_error_.address = addr;
Christopher Ferris55d22ef2017-04-04 10:41:31 -0700194 return false;
195 }
196 stack_.push_front(value);
197 return true;
198}
199
200template <typename AddressType>
201bool 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
209template <typename AddressType>
210bool DwarfOp<AddressType>::op_dup() {
211 stack_.push_front(StackAt(0));
212 return true;
213}
214
215template <typename AddressType>
216bool DwarfOp<AddressType>::op_drop() {
217 StackPop();
218 return true;
219}
220
221template <typename AddressType>
222bool DwarfOp<AddressType>::op_over() {
223 stack_.push_front(StackAt(1));
224 return true;
225}
226
227template <typename AddressType>
228bool DwarfOp<AddressType>::op_pick() {
229 AddressType index = OperandAt(0);
230 if (index > StackSize()) {
Christopher Ferris2fcf4cf2018-01-23 17:52:23 -0800231 last_error_.code = DWARF_ERROR_STACK_INDEX_NOT_VALID;
Christopher Ferris55d22ef2017-04-04 10:41:31 -0700232 return false;
233 }
234 stack_.push_front(StackAt(index));
235 return true;
236}
237
238template <typename AddressType>
239bool 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
246template <typename AddressType>
247bool 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
255template <typename AddressType>
256bool 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
265template <typename AddressType>
266bool DwarfOp<AddressType>::op_and() {
267 AddressType top = StackPop();
268 stack_[0] &= top;
269 return true;
270}
271
272template <typename AddressType>
273bool DwarfOp<AddressType>::op_div() {
274 AddressType top = StackPop();
275 if (top == 0) {
Christopher Ferris2fcf4cf2018-01-23 17:52:23 -0800276 last_error_.code = DWARF_ERROR_ILLEGAL_VALUE;
Christopher Ferris55d22ef2017-04-04 10:41:31 -0700277 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
285template <typename AddressType>
286bool DwarfOp<AddressType>::op_minus() {
287 AddressType top = StackPop();
288 stack_[0] -= top;
289 return true;
290}
291
292template <typename AddressType>
293bool DwarfOp<AddressType>::op_mod() {
294 AddressType top = StackPop();
295 if (top == 0) {
Christopher Ferris2fcf4cf2018-01-23 17:52:23 -0800296 last_error_.code = DWARF_ERROR_ILLEGAL_VALUE;
Christopher Ferris55d22ef2017-04-04 10:41:31 -0700297 return false;
298 }
299 stack_[0] %= top;
300 return true;
301}
302
303template <typename AddressType>
304bool DwarfOp<AddressType>::op_mul() {
305 AddressType top = StackPop();
306 stack_[0] *= top;
307 return true;
308}
309
310template <typename AddressType>
311bool 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
317template <typename AddressType>
318bool DwarfOp<AddressType>::op_not() {
319 stack_[0] = ~stack_[0];
320 return true;
321}
322
323template <typename AddressType>
324bool DwarfOp<AddressType>::op_or() {
325 AddressType top = StackPop();
326 stack_[0] |= top;
327 return true;
328}
329
330template <typename AddressType>
331bool DwarfOp<AddressType>::op_plus() {
332 AddressType top = StackPop();
333 stack_[0] += top;
334 return true;
335}
336
337template <typename AddressType>
338bool DwarfOp<AddressType>::op_plus_uconst() {
339 stack_[0] += OperandAt(0);
340 return true;
341}
342
343template <typename AddressType>
344bool DwarfOp<AddressType>::op_shl() {
345 AddressType top = StackPop();
346 stack_[0] <<= top;
347 return true;
348}
349
350template <typename AddressType>
351bool DwarfOp<AddressType>::op_shr() {
352 AddressType top = StackPop();
353 stack_[0] >>= top;
354 return true;
355}
356
357template <typename AddressType>
358bool 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
365template <typename AddressType>
366bool DwarfOp<AddressType>::op_xor() {
367 AddressType top = StackPop();
368 stack_[0] ^= top;
369 return true;
370}
371
372template <typename AddressType>
373bool 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
387template <typename AddressType>
388bool DwarfOp<AddressType>::op_eq() {
389 AddressType top = StackPop();
390 stack_[0] = bool_to_dwarf_bool(stack_[0] == top);
391 return true;
392}
393
394template <typename AddressType>
395bool DwarfOp<AddressType>::op_ge() {
396 AddressType top = StackPop();
397 stack_[0] = bool_to_dwarf_bool(stack_[0] >= top);
398 return true;
399}
400
401template <typename AddressType>
402bool DwarfOp<AddressType>::op_gt() {
403 AddressType top = StackPop();
404 stack_[0] = bool_to_dwarf_bool(stack_[0] > top);
405 return true;
406}
407
408template <typename AddressType>
409bool DwarfOp<AddressType>::op_le() {
410 AddressType top = StackPop();
411 stack_[0] = bool_to_dwarf_bool(stack_[0] <= top);
412 return true;
413}
414
415template <typename AddressType>
416bool DwarfOp<AddressType>::op_lt() {
417 AddressType top = StackPop();
418 stack_[0] = bool_to_dwarf_bool(stack_[0] < top);
419 return true;
420}
421
422template <typename AddressType>
423bool DwarfOp<AddressType>::op_ne() {
424 AddressType top = StackPop();
425 stack_[0] = bool_to_dwarf_bool(stack_[0] != top);
426 return true;
427}
428
429template <typename AddressType>
430bool 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
437template <typename AddressType>
438bool DwarfOp<AddressType>::op_lit() {
439 stack_.push_front(cur_op() - 0x30);
440 return true;
441}
442
443template <typename AddressType>
444bool DwarfOp<AddressType>::op_reg() {
445 is_register_ = true;
446 stack_.push_front(cur_op() - 0x50);
447 return true;
448}
449
450template <typename AddressType>
451bool 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.
460template <typename AddressType>
461bool DwarfOp<AddressType>::op_breg() {
462 uint16_t reg = cur_op() - 0x70;
Christopher Ferris559c7f22018-02-12 20:18:03 -0800463 if (reg >= regs_info_->Total()) {
Christopher Ferris2fcf4cf2018-01-23 17:52:23 -0800464 last_error_.code = DWARF_ERROR_ILLEGAL_VALUE;
Christopher Ferris55d22ef2017-04-04 10:41:31 -0700465 return false;
466 }
Christopher Ferris559c7f22018-02-12 20:18:03 -0800467 stack_.push_front(regs_info_->Get(reg) + OperandAt(0));
Christopher Ferris55d22ef2017-04-04 10:41:31 -0700468 return true;
469}
470
471template <typename AddressType>
472bool DwarfOp<AddressType>::op_bregx() {
473 AddressType reg = OperandAt(0);
Christopher Ferris559c7f22018-02-12 20:18:03 -0800474 if (reg >= regs_info_->Total()) {
Christopher Ferris2fcf4cf2018-01-23 17:52:23 -0800475 last_error_.code = DWARF_ERROR_ILLEGAL_VALUE;
Christopher Ferris55d22ef2017-04-04 10:41:31 -0700476 return false;
477 }
Christopher Ferris559c7f22018-02-12 20:18:03 -0800478 stack_.push_front(regs_info_->Get(reg) + OperandAt(1));
Christopher Ferris55d22ef2017-04-04 10:41:31 -0700479 return true;
480}
481
482template <typename AddressType>
483bool DwarfOp<AddressType>::op_nop() {
484 return true;
485}
486
487template <typename AddressType>
488bool DwarfOp<AddressType>::op_not_implemented() {
Christopher Ferris2fcf4cf2018-01-23 17:52:23 -0800489 last_error_.code = DWARF_ERROR_NOT_IMPLEMENTED;
Christopher Ferris55d22ef2017-04-04 10:41:31 -0700490 return false;
491}
492
493// Explicitly instantiate DwarfOp.
494template class DwarfOp<uint32_t>;
495template class DwarfOp<uint64_t>;
Christopher Ferrisd226a512017-07-14 10:37:19 -0700496
497} // namespace unwindstack