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