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