blob: dcf04e6ffb104e5b1aa696a7cdb55ddf043e7f49 [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>
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) {
Christopher Ferris2fcf4cf2018-01-23 17:52:23 -080051 last_error_.code = DWARF_ERROR_TOO_MANY_ITERATIONS;
Christopher Ferris55d22ef2017-04-04 10:41:31 -070052 return false;
53 }
54 }
55 return true;
56}
57
58template <typename AddressType>
59bool DwarfOp<AddressType>::Decode(uint8_t dwarf_version) {
Christopher Ferris2fcf4cf2018-01-23 17:52:23 -080060 last_error_.code = DWARF_ERROR_NONE;
Christopher Ferris55d22ef2017-04-04 10:41:31 -070061 if (!memory_->ReadBytes(&cur_op_, 1)) {
Christopher Ferris2fcf4cf2018-01-23 17:52:23 -080062 last_error_.code = DWARF_ERROR_MEMORY_INVALID;
63 last_error_.address = memory_->cur_offset();
Christopher Ferris55d22ef2017-04-04 10:41:31 -070064 return false;
65 }
66
67 const auto* op = &kCallbackTable[cur_op_];
68 const auto handle_func = op->handle_func;
69 if (handle_func == nullptr) {
Christopher Ferris2fcf4cf2018-01-23 17:52:23 -080070 last_error_.code = DWARF_ERROR_ILLEGAL_VALUE;
Christopher Ferris55d22ef2017-04-04 10:41:31 -070071 return false;
72 }
73
74 // Check for an unsupported opcode.
75 if (dwarf_version < op->supported_version) {
Christopher Ferris2fcf4cf2018-01-23 17:52:23 -080076 last_error_.code = DWARF_ERROR_ILLEGAL_VALUE;
Christopher Ferris55d22ef2017-04-04 10:41:31 -070077 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) {
Christopher Ferris2fcf4cf2018-01-23 17:52:23 -080082 last_error_.code = DWARF_ERROR_STACK_INDEX_NOT_VALID;
Christopher Ferris55d22ef2017-04-04 10:41:31 -070083 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)) {
Christopher Ferris2fcf4cf2018-01-23 17:52:23 -080090 last_error_.code = DWARF_ERROR_MEMORY_INVALID;
91 last_error_.address = memory_->cur_offset();
Christopher Ferris55d22ef2017-04-04 10:41:31 -070092 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;
Josh Gaoef35aa52017-10-18 11:44:51 -0700146 if (!regular_memory()->ReadFully(addr, &value, sizeof(value))) {
Christopher Ferris2fcf4cf2018-01-23 17:52:23 -0800147 last_error_.code = DWARF_ERROR_MEMORY_INVALID;
148 last_error_.address = addr;
Christopher Ferris55d22ef2017-04-04 10:41:31 -0700149 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) {
Christopher Ferris2fcf4cf2018-01-23 17:52:23 -0800159 last_error_.code = DWARF_ERROR_ILLEGAL_VALUE;
Christopher Ferris55d22ef2017-04-04 10:41:31 -0700160 return false;
161 }
162 // Read the address and dereference it.
163 AddressType addr = StackPop();
164 AddressType value = 0;
Josh Gaoef35aa52017-10-18 11:44:51 -0700165 if (!regular_memory()->ReadFully(addr, &value, bytes_to_read)) {
Christopher Ferris2fcf4cf2018-01-23 17:52:23 -0800166 last_error_.code = DWARF_ERROR_MEMORY_INVALID;
167 last_error_.address = addr;
Christopher Ferris55d22ef2017-04-04 10:41:31 -0700168 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()) {
Christopher Ferris2fcf4cf2018-01-23 17:52:23 -0800205 last_error_.code = DWARF_ERROR_STACK_INDEX_NOT_VALID;
Christopher Ferris55d22ef2017-04-04 10:41:31 -0700206 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) {
Christopher Ferris2fcf4cf2018-01-23 17:52:23 -0800250 last_error_.code = DWARF_ERROR_ILLEGAL_VALUE;
Christopher Ferris55d22ef2017-04-04 10:41:31 -0700251 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) {
Christopher Ferris2fcf4cf2018-01-23 17:52:23 -0800270 last_error_.code = DWARF_ERROR_ILLEGAL_VALUE;
Christopher Ferris55d22ef2017-04-04 10:41:31 -0700271 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()) {
Christopher Ferris2fcf4cf2018-01-23 17:52:23 -0800438 last_error_.code = DWARF_ERROR_ILLEGAL_VALUE;
Christopher Ferris55d22ef2017-04-04 10:41:31 -0700439 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()) {
Christopher Ferris2fcf4cf2018-01-23 17:52:23 -0800449 last_error_.code = DWARF_ERROR_ILLEGAL_VALUE;
Christopher Ferris55d22ef2017-04-04 10:41:31 -0700450 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() {
Christopher Ferris2fcf4cf2018-01-23 17:52:23 -0800463 last_error_.code = DWARF_ERROR_NOT_IMPLEMENTED;
Christopher Ferris55d22ef2017-04-04 10:41:31 -0700464 return false;
465}
466
467// Explicitly instantiate DwarfOp.
468template class DwarfOp<uint32_t>;
469template class DwarfOp<uint64_t>;
Christopher Ferrisd226a512017-07-14 10:37:19 -0700470
471} // namespace unwindstack