155d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris/*
255d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris * Copyright (C) 2017 The Android Open Source Project
355d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris *
455d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris * Licensed under the Apache License, Version 2.0 (the "License");
555d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris * you may not use this file except in compliance with the License.
655d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris * You may obtain a copy of the License at
755d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris *
855d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris *      http://www.apache.org/licenses/LICENSE-2.0
955d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris *
1055d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris * Unless required by applicable law or agreed to in writing, software
1155d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris * distributed under the License is distributed on an "AS IS" BASIS,
1255d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1355d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris * See the License for the specific language governing permissions and
1455d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris * limitations under the License.
1555d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris */
1655d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris
1755d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris#include <stdint.h>
1855d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris
1955d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris#include <deque>
2055d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris#include <string>
2155d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris#include <vector>
2255d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris
2355d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris#include <android-base/stringprintf.h>
2455d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris
252fcf4cf13e9aefa8c312084af12ca2d712a6ead3Christopher Ferris#include <unwindstack/DwarfError.h>
26d226a5140989f509a0ed3e2723f05d5fc93ce8dfChristopher Ferris#include <unwindstack/DwarfMemory.h>
27d226a5140989f509a0ed3e2723f05d5fc93ce8dfChristopher Ferris#include <unwindstack/Log.h>
28d226a5140989f509a0ed3e2723f05d5fc93ce8dfChristopher Ferris#include <unwindstack/Memory.h>
29d226a5140989f509a0ed3e2723f05d5fc93ce8dfChristopher Ferris#include <unwindstack/Regs.h>
30d226a5140989f509a0ed3e2723f05d5fc93ce8dfChristopher Ferris
3155d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris#include "DwarfOp.h"
32d226a5140989f509a0ed3e2723f05d5fc93ce8dfChristopher Ferris
33d226a5140989f509a0ed3e2723f05d5fc93ce8dfChristopher Ferrisnamespace unwindstack {
3455d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris
3555d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferristemplate <typename AddressType>
3655d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferrisconstexpr typename DwarfOp<AddressType>::OpCallback DwarfOp<AddressType>::kCallbackTable[256];
3755d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris
3855d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferristemplate <typename AddressType>
39559c7f209295a7070515bba9fa3985edf53d13a0Christopher Ferrisbool DwarfOp<AddressType>::Eval(uint64_t start, uint64_t end) {
4055d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  is_register_ = false;
4155d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  stack_.clear();
4255d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  memory_->set_cur_offset(start);
43559c7f209295a7070515bba9fa3985edf53d13a0Christopher Ferris  dex_pc_set_ = false;
44559c7f209295a7070515bba9fa3985edf53d13a0Christopher Ferris
45559c7f209295a7070515bba9fa3985edf53d13a0Christopher Ferris  // Unroll the first Decode calls to be able to check for a special
46559c7f209295a7070515bba9fa3985edf53d13a0Christopher Ferris  // sequence of ops and values that indicate this is the dex pc.
47559c7f209295a7070515bba9fa3985edf53d13a0Christopher Ferris  // The pattern is:
48559c7f209295a7070515bba9fa3985edf53d13a0Christopher Ferris  //   OP_const4u (0x0c)  'D' 'E' 'X' '1'
49559c7f209295a7070515bba9fa3985edf53d13a0Christopher Ferris  //   OP_drop (0x13)
50559c7f209295a7070515bba9fa3985edf53d13a0Christopher Ferris  if (memory_->cur_offset() < end) {
51559c7f209295a7070515bba9fa3985edf53d13a0Christopher Ferris    if (!Decode()) {
52559c7f209295a7070515bba9fa3985edf53d13a0Christopher Ferris      return false;
53559c7f209295a7070515bba9fa3985edf53d13a0Christopher Ferris    }
54559c7f209295a7070515bba9fa3985edf53d13a0Christopher Ferris  } else {
55559c7f209295a7070515bba9fa3985edf53d13a0Christopher Ferris    return true;
56559c7f209295a7070515bba9fa3985edf53d13a0Christopher Ferris  }
57559c7f209295a7070515bba9fa3985edf53d13a0Christopher Ferris  bool check_for_drop;
58559c7f209295a7070515bba9fa3985edf53d13a0Christopher Ferris  if (cur_op_ == 0x0c && operands_.back() == 0x31584544) {
59559c7f209295a7070515bba9fa3985edf53d13a0Christopher Ferris    check_for_drop = true;
60559c7f209295a7070515bba9fa3985edf53d13a0Christopher Ferris  } else {
61559c7f209295a7070515bba9fa3985edf53d13a0Christopher Ferris    check_for_drop = false;
62559c7f209295a7070515bba9fa3985edf53d13a0Christopher Ferris  }
63559c7f209295a7070515bba9fa3985edf53d13a0Christopher Ferris  if (memory_->cur_offset() < end) {
64559c7f209295a7070515bba9fa3985edf53d13a0Christopher Ferris    if (!Decode()) {
65559c7f209295a7070515bba9fa3985edf53d13a0Christopher Ferris      return false;
66559c7f209295a7070515bba9fa3985edf53d13a0Christopher Ferris    }
67559c7f209295a7070515bba9fa3985edf53d13a0Christopher Ferris  } else {
68559c7f209295a7070515bba9fa3985edf53d13a0Christopher Ferris    return true;
69559c7f209295a7070515bba9fa3985edf53d13a0Christopher Ferris  }
70559c7f209295a7070515bba9fa3985edf53d13a0Christopher Ferris
71559c7f209295a7070515bba9fa3985edf53d13a0Christopher Ferris  if (check_for_drop && cur_op_ == 0x13) {
72559c7f209295a7070515bba9fa3985edf53d13a0Christopher Ferris    dex_pc_set_ = true;
73559c7f209295a7070515bba9fa3985edf53d13a0Christopher Ferris  }
74559c7f209295a7070515bba9fa3985edf53d13a0Christopher Ferris
75559c7f209295a7070515bba9fa3985edf53d13a0Christopher Ferris  uint32_t iterations = 2;
7655d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  while (memory_->cur_offset() < end) {
77559c7f209295a7070515bba9fa3985edf53d13a0Christopher Ferris    if (!Decode()) {
7855d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris      return false;
7955d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris    }
8055d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris    // To protect against a branch that creates an infinite loop,
8155d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris    // terminate if the number of iterations gets too high.
8255d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris    if (iterations++ == 1000) {
832fcf4cf13e9aefa8c312084af12ca2d712a6ead3Christopher Ferris      last_error_.code = DWARF_ERROR_TOO_MANY_ITERATIONS;
8455d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris      return false;
8555d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris    }
8655d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  }
8755d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  return true;
8855d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris}
8955d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris
9055d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferristemplate <typename AddressType>
91559c7f209295a7070515bba9fa3985edf53d13a0Christopher Ferrisbool DwarfOp<AddressType>::Decode() {
922fcf4cf13e9aefa8c312084af12ca2d712a6ead3Christopher Ferris  last_error_.code = DWARF_ERROR_NONE;
9355d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  if (!memory_->ReadBytes(&cur_op_, 1)) {
942fcf4cf13e9aefa8c312084af12ca2d712a6ead3Christopher Ferris    last_error_.code = DWARF_ERROR_MEMORY_INVALID;
952fcf4cf13e9aefa8c312084af12ca2d712a6ead3Christopher Ferris    last_error_.address = memory_->cur_offset();
9655d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris    return false;
9755d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  }
9855d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris
9955d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  const auto* op = &kCallbackTable[cur_op_];
10055d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  const auto handle_func = op->handle_func;
10155d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  if (handle_func == nullptr) {
1022fcf4cf13e9aefa8c312084af12ca2d712a6ead3Christopher Ferris    last_error_.code = DWARF_ERROR_ILLEGAL_VALUE;
10355d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris    return false;
10455d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  }
10555d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris
10655d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  // Make sure that the required number of stack elements is available.
10755d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  if (stack_.size() < op->num_required_stack_values) {
1082fcf4cf13e9aefa8c312084af12ca2d712a6ead3Christopher Ferris    last_error_.code = DWARF_ERROR_STACK_INDEX_NOT_VALID;
10955d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris    return false;
11055d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  }
11155d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris
11255d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  operands_.clear();
11355d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  for (size_t i = 0; i < op->num_operands; i++) {
11455d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris    uint64_t value;
11555d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris    if (!memory_->ReadEncodedValue<AddressType>(op->operands[i], &value)) {
1162fcf4cf13e9aefa8c312084af12ca2d712a6ead3Christopher Ferris      last_error_.code = DWARF_ERROR_MEMORY_INVALID;
1172fcf4cf13e9aefa8c312084af12ca2d712a6ead3Christopher Ferris      last_error_.address = memory_->cur_offset();
11855d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris      return false;
11955d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris    }
12055d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris    operands_.push_back(value);
12155d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  }
12255d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  return (this->*handle_func)();
12355d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris}
12455d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris
12555d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferristemplate <typename AddressType>
12655d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferrisvoid DwarfOp<AddressType>::GetLogInfo(uint64_t start, uint64_t end,
12755d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris                                      std::vector<std::string>* lines) {
12855d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  memory_->set_cur_offset(start);
12955d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  while (memory_->cur_offset() < end) {
13055d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris    uint8_t cur_op;
13155d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris    if (!memory_->ReadBytes(&cur_op, 1)) {
13255d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris      return;
13355d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris    }
13455d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris
13555d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris    std::string raw_string(android::base::StringPrintf("Raw Data: 0x%02x", cur_op));
13655d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris    std::string log_string;
13755d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris    const auto* op = &kCallbackTable[cur_op];
13855d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris    if (op->handle_func == nullptr) {
13955d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris      log_string = "Illegal";
14055d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris    } else {
14155d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris      log_string = op->name;
14255d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris      uint64_t start_offset = memory_->cur_offset();
14355d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris      for (size_t i = 0; i < op->num_operands; i++) {
14455d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris        uint64_t value;
14555d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris        if (!memory_->ReadEncodedValue<AddressType>(op->operands[i], &value)) {
14655d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris          return;
14755d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris        }
14855d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris        log_string += ' ' + std::to_string(value);
14955d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris      }
15055d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris      uint64_t end_offset = memory_->cur_offset();
15155d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris
15255d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris      memory_->set_cur_offset(start_offset);
15355d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris      for (size_t i = start_offset; i < end_offset; i++) {
15455d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris        uint8_t byte;
15555d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris        if (!memory_->ReadBytes(&byte, 1)) {
15655d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris          return;
15755d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris        }
15855d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris        raw_string += android::base::StringPrintf(" 0x%02x", byte);
15955d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris      }
16055d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris      memory_->set_cur_offset(end_offset);
16155d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris    }
16255d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris    lines->push_back(std::move(log_string));
16355d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris    lines->push_back(std::move(raw_string));
16455d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  }
16555d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris}
16655d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris
16755d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferristemplate <typename AddressType>
16855d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferrisbool DwarfOp<AddressType>::op_deref() {
16955d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  // Read the address and dereference it.
17055d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  AddressType addr = StackPop();
17155d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  AddressType value;
172ef35aa5d40b6404baf702a58527f1cd3a9f42f19Josh Gao  if (!regular_memory()->ReadFully(addr, &value, sizeof(value))) {
1732fcf4cf13e9aefa8c312084af12ca2d712a6ead3Christopher Ferris    last_error_.code = DWARF_ERROR_MEMORY_INVALID;
1742fcf4cf13e9aefa8c312084af12ca2d712a6ead3Christopher Ferris    last_error_.address = addr;
17555d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris    return false;
17655d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  }
17755d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  stack_.push_front(value);
17855d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  return true;
17955d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris}
18055d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris
18155d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferristemplate <typename AddressType>
18255d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferrisbool DwarfOp<AddressType>::op_deref_size() {
18355d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  AddressType bytes_to_read = OperandAt(0);
18455d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  if (bytes_to_read > sizeof(AddressType) || bytes_to_read == 0) {
1852fcf4cf13e9aefa8c312084af12ca2d712a6ead3Christopher Ferris    last_error_.code = DWARF_ERROR_ILLEGAL_VALUE;
18655d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris    return false;
18755d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  }
18855d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  // Read the address and dereference it.
18955d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  AddressType addr = StackPop();
19055d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  AddressType value = 0;
191ef35aa5d40b6404baf702a58527f1cd3a9f42f19Josh Gao  if (!regular_memory()->ReadFully(addr, &value, bytes_to_read)) {
1922fcf4cf13e9aefa8c312084af12ca2d712a6ead3Christopher Ferris    last_error_.code = DWARF_ERROR_MEMORY_INVALID;
1932fcf4cf13e9aefa8c312084af12ca2d712a6ead3Christopher Ferris    last_error_.address = addr;
19455d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris    return false;
19555d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  }
19655d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  stack_.push_front(value);
19755d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  return true;
19855d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris}
19955d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris
20055d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferristemplate <typename AddressType>
20155d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferrisbool DwarfOp<AddressType>::op_push() {
20255d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  // Push all of the operands.
20355d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  for (auto operand : operands_) {
20455d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris    stack_.push_front(operand);
20555d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  }
20655d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  return true;
20755d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris}
20855d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris
20955d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferristemplate <typename AddressType>
21055d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferrisbool DwarfOp<AddressType>::op_dup() {
21155d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  stack_.push_front(StackAt(0));
21255d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  return true;
21355d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris}
21455d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris
21555d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferristemplate <typename AddressType>
21655d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferrisbool DwarfOp<AddressType>::op_drop() {
21755d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  StackPop();
21855d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  return true;
21955d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris}
22055d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris
22155d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferristemplate <typename AddressType>
22255d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferrisbool DwarfOp<AddressType>::op_over() {
22355d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  stack_.push_front(StackAt(1));
22455d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  return true;
22555d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris}
22655d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris
22755d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferristemplate <typename AddressType>
22855d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferrisbool DwarfOp<AddressType>::op_pick() {
22955d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  AddressType index = OperandAt(0);
23055d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  if (index > StackSize()) {
2312fcf4cf13e9aefa8c312084af12ca2d712a6ead3Christopher Ferris    last_error_.code = DWARF_ERROR_STACK_INDEX_NOT_VALID;
23255d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris    return false;
23355d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  }
23455d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  stack_.push_front(StackAt(index));
23555d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  return true;
23655d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris}
23755d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris
23855d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferristemplate <typename AddressType>
23955d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferrisbool DwarfOp<AddressType>::op_swap() {
24055d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  AddressType old_value = stack_[0];
24155d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  stack_[0] = stack_[1];
24255d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  stack_[1] = old_value;
24355d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  return true;
24455d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris}
24555d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris
24655d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferristemplate <typename AddressType>
24755d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferrisbool DwarfOp<AddressType>::op_rot() {
24855d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  AddressType top = stack_[0];
24955d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  stack_[0] = stack_[1];
25055d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  stack_[1] = stack_[2];
25155d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  stack_[2] = top;
25255d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  return true;
25355d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris}
25455d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris
25555d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferristemplate <typename AddressType>
25655d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferrisbool DwarfOp<AddressType>::op_abs() {
25755d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  SignedType signed_value = static_cast<SignedType>(stack_[0]);
25855d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  if (signed_value < 0) {
25955d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris    signed_value = -signed_value;
26055d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  }
26155d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  stack_[0] = static_cast<AddressType>(signed_value);
26255d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  return true;
26355d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris}
26455d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris
26555d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferristemplate <typename AddressType>
26655d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferrisbool DwarfOp<AddressType>::op_and() {
26755d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  AddressType top = StackPop();
26855d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  stack_[0] &= top;
26955d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  return true;
27055d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris}
27155d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris
27255d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferristemplate <typename AddressType>
27355d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferrisbool DwarfOp<AddressType>::op_div() {
27455d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  AddressType top = StackPop();
27555d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  if (top == 0) {
2762fcf4cf13e9aefa8c312084af12ca2d712a6ead3Christopher Ferris    last_error_.code = DWARF_ERROR_ILLEGAL_VALUE;
27755d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris    return false;
27855d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  }
27955d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  SignedType signed_divisor = static_cast<SignedType>(top);
28055d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  SignedType signed_dividend = static_cast<SignedType>(stack_[0]);
28155d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  stack_[0] = static_cast<AddressType>(signed_dividend / signed_divisor);
28255d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  return true;
28355d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris}
28455d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris
28555d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferristemplate <typename AddressType>
28655d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferrisbool DwarfOp<AddressType>::op_minus() {
28755d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  AddressType top = StackPop();
28855d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  stack_[0] -= top;
28955d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  return true;
29055d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris}
29155d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris
29255d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferristemplate <typename AddressType>
29355d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferrisbool DwarfOp<AddressType>::op_mod() {
29455d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  AddressType top = StackPop();
29555d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  if (top == 0) {
2962fcf4cf13e9aefa8c312084af12ca2d712a6ead3Christopher Ferris    last_error_.code = DWARF_ERROR_ILLEGAL_VALUE;
29755d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris    return false;
29855d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  }
29955d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  stack_[0] %= top;
30055d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  return true;
30155d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris}
30255d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris
30355d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferristemplate <typename AddressType>
30455d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferrisbool DwarfOp<AddressType>::op_mul() {
30555d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  AddressType top = StackPop();
30655d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  stack_[0] *= top;
30755d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  return true;
30855d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris}
30955d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris
31055d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferristemplate <typename AddressType>
31155d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferrisbool DwarfOp<AddressType>::op_neg() {
31255d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  SignedType signed_value = static_cast<SignedType>(stack_[0]);
31355d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  stack_[0] = static_cast<AddressType>(-signed_value);
31455d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  return true;
31555d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris}
31655d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris
31755d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferristemplate <typename AddressType>
31855d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferrisbool DwarfOp<AddressType>::op_not() {
31955d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  stack_[0] = ~stack_[0];
32055d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  return true;
32155d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris}
32255d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris
32355d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferristemplate <typename AddressType>
32455d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferrisbool DwarfOp<AddressType>::op_or() {
32555d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  AddressType top = StackPop();
32655d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  stack_[0] |= top;
32755d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  return true;
32855d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris}
32955d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris
33055d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferristemplate <typename AddressType>
33155d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferrisbool DwarfOp<AddressType>::op_plus() {
33255d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  AddressType top = StackPop();
33355d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  stack_[0] += top;
33455d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  return true;
33555d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris}
33655d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris
33755d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferristemplate <typename AddressType>
33855d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferrisbool DwarfOp<AddressType>::op_plus_uconst() {
33955d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  stack_[0] += OperandAt(0);
34055d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  return true;
34155d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris}
34255d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris
34355d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferristemplate <typename AddressType>
34455d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferrisbool DwarfOp<AddressType>::op_shl() {
34555d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  AddressType top = StackPop();
34655d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  stack_[0] <<= top;
34755d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  return true;
34855d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris}
34955d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris
35055d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferristemplate <typename AddressType>
35155d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferrisbool DwarfOp<AddressType>::op_shr() {
35255d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  AddressType top = StackPop();
35355d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  stack_[0] >>= top;
35455d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  return true;
35555d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris}
35655d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris
35755d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferristemplate <typename AddressType>
35855d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferrisbool DwarfOp<AddressType>::op_shra() {
35955d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  AddressType top = StackPop();
36055d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  SignedType signed_value = static_cast<SignedType>(stack_[0]) >> top;
36155d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  stack_[0] = static_cast<AddressType>(signed_value);
36255d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  return true;
36355d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris}
36455d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris
36555d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferristemplate <typename AddressType>
36655d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferrisbool DwarfOp<AddressType>::op_xor() {
36755d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  AddressType top = StackPop();
36855d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  stack_[0] ^= top;
36955d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  return true;
37055d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris}
37155d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris
37255d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferristemplate <typename AddressType>
37355d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferrisbool DwarfOp<AddressType>::op_bra() {
37455d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  // Requires one stack element.
37555d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  AddressType top = StackPop();
37655d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  int16_t offset = static_cast<int16_t>(OperandAt(0));
37755d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  uint64_t cur_offset;
37855d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  if (top != 0) {
37955d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris    cur_offset = memory_->cur_offset() + offset;
38055d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  } else {
38155d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris    cur_offset = memory_->cur_offset() - offset;
38255d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  }
38355d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  memory_->set_cur_offset(cur_offset);
38455d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  return true;
38555d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris}
38655d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris
38755d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferristemplate <typename AddressType>
38855d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferrisbool DwarfOp<AddressType>::op_eq() {
38955d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  AddressType top = StackPop();
39055d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  stack_[0] = bool_to_dwarf_bool(stack_[0] == top);
39155d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  return true;
39255d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris}
39355d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris
39455d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferristemplate <typename AddressType>
39555d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferrisbool DwarfOp<AddressType>::op_ge() {
39655d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  AddressType top = StackPop();
39755d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  stack_[0] = bool_to_dwarf_bool(stack_[0] >= top);
39855d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  return true;
39955d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris}
40055d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris
40155d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferristemplate <typename AddressType>
40255d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferrisbool DwarfOp<AddressType>::op_gt() {
40355d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  AddressType top = StackPop();
40455d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  stack_[0] = bool_to_dwarf_bool(stack_[0] > top);
40555d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  return true;
40655d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris}
40755d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris
40855d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferristemplate <typename AddressType>
40955d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferrisbool DwarfOp<AddressType>::op_le() {
41055d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  AddressType top = StackPop();
41155d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  stack_[0] = bool_to_dwarf_bool(stack_[0] <= top);
41255d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  return true;
41355d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris}
41455d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris
41555d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferristemplate <typename AddressType>
41655d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferrisbool DwarfOp<AddressType>::op_lt() {
41755d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  AddressType top = StackPop();
41855d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  stack_[0] = bool_to_dwarf_bool(stack_[0] < top);
41955d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  return true;
42055d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris}
42155d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris
42255d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferristemplate <typename AddressType>
42355d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferrisbool DwarfOp<AddressType>::op_ne() {
42455d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  AddressType top = StackPop();
42555d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  stack_[0] = bool_to_dwarf_bool(stack_[0] != top);
42655d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  return true;
42755d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris}
42855d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris
42955d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferristemplate <typename AddressType>
43055d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferrisbool DwarfOp<AddressType>::op_skip() {
43155d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  int16_t offset = static_cast<int16_t>(OperandAt(0));
43255d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  uint64_t cur_offset = memory_->cur_offset() + offset;
43355d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  memory_->set_cur_offset(cur_offset);
43455d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  return true;
43555d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris}
43655d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris
43755d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferristemplate <typename AddressType>
43855d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferrisbool DwarfOp<AddressType>::op_lit() {
43955d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  stack_.push_front(cur_op() - 0x30);
44055d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  return true;
44155d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris}
44255d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris
44355d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferristemplate <typename AddressType>
44455d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferrisbool DwarfOp<AddressType>::op_reg() {
44555d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  is_register_ = true;
44655d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  stack_.push_front(cur_op() - 0x50);
44755d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  return true;
44855d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris}
44955d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris
45055d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferristemplate <typename AddressType>
45155d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferrisbool DwarfOp<AddressType>::op_regx() {
45255d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  is_register_ = true;
45355d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  stack_.push_front(OperandAt(0));
45455d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  return true;
45555d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris}
45655d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris
45755d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris// It's not clear for breg/bregx, if this op should read the current
45855d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris// value of the register, or where we think that register is located.
45955d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris// For simplicity, the code will read the value before doing the unwind.
46055d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferristemplate <typename AddressType>
46155d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferrisbool DwarfOp<AddressType>::op_breg() {
46255d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  uint16_t reg = cur_op() - 0x70;
463559c7f209295a7070515bba9fa3985edf53d13a0Christopher Ferris  if (reg >= regs_info_->Total()) {
4642fcf4cf13e9aefa8c312084af12ca2d712a6ead3Christopher Ferris    last_error_.code = DWARF_ERROR_ILLEGAL_VALUE;
46555d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris    return false;
46655d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  }
467559c7f209295a7070515bba9fa3985edf53d13a0Christopher Ferris  stack_.push_front(regs_info_->Get(reg) + OperandAt(0));
46855d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  return true;
46955d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris}
47055d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris
47155d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferristemplate <typename AddressType>
47255d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferrisbool DwarfOp<AddressType>::op_bregx() {
47355d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  AddressType reg = OperandAt(0);
474559c7f209295a7070515bba9fa3985edf53d13a0Christopher Ferris  if (reg >= regs_info_->Total()) {
4752fcf4cf13e9aefa8c312084af12ca2d712a6ead3Christopher Ferris    last_error_.code = DWARF_ERROR_ILLEGAL_VALUE;
47655d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris    return false;
47755d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  }
478559c7f209295a7070515bba9fa3985edf53d13a0Christopher Ferris  stack_.push_front(regs_info_->Get(reg) + OperandAt(1));
47955d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  return true;
48055d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris}
48155d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris
48255d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferristemplate <typename AddressType>
48355d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferrisbool DwarfOp<AddressType>::op_nop() {
48455d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  return true;
48555d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris}
48655d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris
48755d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferristemplate <typename AddressType>
48855d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferrisbool DwarfOp<AddressType>::op_not_implemented() {
4892fcf4cf13e9aefa8c312084af12ca2d712a6ead3Christopher Ferris  last_error_.code = DWARF_ERROR_NOT_IMPLEMENTED;
49055d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  return false;
49155d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris}
49255d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris
49355d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris// Explicitly instantiate DwarfOp.
49455d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferristemplate class DwarfOp<uint32_t>;
49555d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferristemplate class DwarfOp<uint64_t>;
496d226a5140989f509a0ed3e2723f05d5fc93ce8dfChristopher Ferris
497d226a5140989f509a0ed3e2723f05d5fc93ce8dfChristopher Ferris}  // namespace unwindstack
498