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
25d226a5140989f509a0ed3e2723f05d5fc93ce8dfChristopher Ferris#include <unwindstack/DwarfMemory.h>
26d226a5140989f509a0ed3e2723f05d5fc93ce8dfChristopher Ferris#include <unwindstack/Log.h>
27d226a5140989f509a0ed3e2723f05d5fc93ce8dfChristopher Ferris#include <unwindstack/Memory.h>
28d226a5140989f509a0ed3e2723f05d5fc93ce8dfChristopher Ferris#include <unwindstack/Regs.h>
29d226a5140989f509a0ed3e2723f05d5fc93ce8dfChristopher Ferris
3055d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris#include "DwarfError.h"
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>
3955d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferrisbool DwarfOp<AddressType>::Eval(uint64_t start, uint64_t end, uint8_t dwarf_version) {
4055d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  uint32_t iterations = 0;
4155d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  is_register_ = false;
4255d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  stack_.clear();
4355d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  memory_->set_cur_offset(start);
4455d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  while (memory_->cur_offset() < end) {
4555d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris    if (!Decode(dwarf_version)) {
4655d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris      return false;
4755d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris    }
4855d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris    // To protect against a branch that creates an infinite loop,
4955d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris    // terminate if the number of iterations gets too high.
5055d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris    if (iterations++ == 1000) {
5155d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris      last_error_ = DWARF_ERROR_TOO_MANY_ITERATIONS;
5255d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris      return false;
5355d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris    }
5455d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  }
5555d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  return true;
5655d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris}
5755d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris
5855d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferristemplate <typename AddressType>
5955d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferrisbool DwarfOp<AddressType>::Decode(uint8_t dwarf_version) {
6055d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  last_error_ = DWARF_ERROR_NONE;
6155d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  if (!memory_->ReadBytes(&cur_op_, 1)) {
6255d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris    last_error_ = DWARF_ERROR_MEMORY_INVALID;
6355d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris    return false;
6455d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  }
6555d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris
6655d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  const auto* op = &kCallbackTable[cur_op_];
6755d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  const auto handle_func = op->handle_func;
6855d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  if (handle_func == nullptr) {
6955d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris    last_error_ = DWARF_ERROR_ILLEGAL_VALUE;
7055d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris    return false;
7155d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  }
7255d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris
7355d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  // Check for an unsupported opcode.
7455d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  if (dwarf_version < op->supported_version) {
7555d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris    last_error_ = DWARF_ERROR_ILLEGAL_VALUE;
7655d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris    return false;
7755d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  }
7855d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris
7955d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  // Make sure that the required number of stack elements is available.
8055d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  if (stack_.size() < op->num_required_stack_values) {
8155d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris    last_error_ = DWARF_ERROR_STACK_INDEX_NOT_VALID;
8255d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris    return false;
8355d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  }
8455d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris
8555d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  operands_.clear();
8655d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  for (size_t i = 0; i < op->num_operands; i++) {
8755d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris    uint64_t value;
8855d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris    if (!memory_->ReadEncodedValue<AddressType>(op->operands[i], &value)) {
8955d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris      last_error_ = DWARF_ERROR_MEMORY_INVALID;
9055d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris      return false;
9155d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris    }
9255d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris    operands_.push_back(value);
9355d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  }
9455d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  return (this->*handle_func)();
9555d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris}
9655d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris
9755d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferristemplate <typename AddressType>
9855d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferrisvoid DwarfOp<AddressType>::GetLogInfo(uint64_t start, uint64_t end,
9955d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris                                      std::vector<std::string>* lines) {
10055d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  memory_->set_cur_offset(start);
10155d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  while (memory_->cur_offset() < end) {
10255d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris    uint8_t cur_op;
10355d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris    if (!memory_->ReadBytes(&cur_op, 1)) {
10455d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris      return;
10555d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris    }
10655d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris
10755d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris    std::string raw_string(android::base::StringPrintf("Raw Data: 0x%02x", cur_op));
10855d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris    std::string log_string;
10955d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris    const auto* op = &kCallbackTable[cur_op];
11055d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris    if (op->handle_func == nullptr) {
11155d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris      log_string = "Illegal";
11255d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris    } else {
11355d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris      log_string = op->name;
11455d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris      uint64_t start_offset = memory_->cur_offset();
11555d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris      for (size_t i = 0; i < op->num_operands; i++) {
11655d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris        uint64_t value;
11755d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris        if (!memory_->ReadEncodedValue<AddressType>(op->operands[i], &value)) {
11855d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris          return;
11955d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris        }
12055d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris        log_string += ' ' + std::to_string(value);
12155d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris      }
12255d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris      uint64_t end_offset = memory_->cur_offset();
12355d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris
12455d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris      memory_->set_cur_offset(start_offset);
12555d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris      for (size_t i = start_offset; i < end_offset; i++) {
12655d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris        uint8_t byte;
12755d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris        if (!memory_->ReadBytes(&byte, 1)) {
12855d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris          return;
12955d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris        }
13055d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris        raw_string += android::base::StringPrintf(" 0x%02x", byte);
13155d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris      }
13255d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris      memory_->set_cur_offset(end_offset);
13355d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris    }
13455d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris    lines->push_back(std::move(log_string));
13555d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris    lines->push_back(std::move(raw_string));
13655d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  }
13755d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris}
13855d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris
13955d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferristemplate <typename AddressType>
14055d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferrisbool DwarfOp<AddressType>::op_deref() {
14155d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  // Read the address and dereference it.
14255d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  AddressType addr = StackPop();
14355d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  AddressType value;
14455d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  if (!regular_memory()->Read(addr, &value, sizeof(value))) {
14555d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris    last_error_ = DWARF_ERROR_MEMORY_INVALID;
14655d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris    return false;
14755d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  }
14855d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  stack_.push_front(value);
14955d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  return true;
15055d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris}
15155d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris
15255d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferristemplate <typename AddressType>
15355d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferrisbool DwarfOp<AddressType>::op_deref_size() {
15455d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  AddressType bytes_to_read = OperandAt(0);
15555d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  if (bytes_to_read > sizeof(AddressType) || bytes_to_read == 0) {
15655d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris    last_error_ = DWARF_ERROR_ILLEGAL_VALUE;
15755d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris    return false;
15855d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  }
15955d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  // Read the address and dereference it.
16055d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  AddressType addr = StackPop();
16155d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  AddressType value = 0;
16255d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  if (!regular_memory()->Read(addr, &value, bytes_to_read)) {
16355d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris    last_error_ = DWARF_ERROR_MEMORY_INVALID;
16455d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris    return false;
16555d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  }
16655d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  stack_.push_front(value);
16755d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  return true;
16855d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris}
16955d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris
17055d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferristemplate <typename AddressType>
17155d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferrisbool DwarfOp<AddressType>::op_push() {
17255d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  // Push all of the operands.
17355d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  for (auto operand : operands_) {
17455d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris    stack_.push_front(operand);
17555d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  }
17655d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  return true;
17755d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris}
17855d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris
17955d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferristemplate <typename AddressType>
18055d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferrisbool DwarfOp<AddressType>::op_dup() {
18155d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  stack_.push_front(StackAt(0));
18255d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  return true;
18355d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris}
18455d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris
18555d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferristemplate <typename AddressType>
18655d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferrisbool DwarfOp<AddressType>::op_drop() {
18755d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  StackPop();
18855d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  return true;
18955d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris}
19055d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris
19155d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferristemplate <typename AddressType>
19255d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferrisbool DwarfOp<AddressType>::op_over() {
19355d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  stack_.push_front(StackAt(1));
19455d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  return true;
19555d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris}
19655d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris
19755d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferristemplate <typename AddressType>
19855d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferrisbool DwarfOp<AddressType>::op_pick() {
19955d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  AddressType index = OperandAt(0);
20055d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  if (index > StackSize()) {
20155d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris    last_error_ = DWARF_ERROR_STACK_INDEX_NOT_VALID;
20255d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris    return false;
20355d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  }
20455d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  stack_.push_front(StackAt(index));
20555d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  return true;
20655d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris}
20755d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris
20855d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferristemplate <typename AddressType>
20955d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferrisbool DwarfOp<AddressType>::op_swap() {
21055d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  AddressType old_value = stack_[0];
21155d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  stack_[0] = stack_[1];
21255d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  stack_[1] = old_value;
21355d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  return true;
21455d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris}
21555d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris
21655d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferristemplate <typename AddressType>
21755d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferrisbool DwarfOp<AddressType>::op_rot() {
21855d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  AddressType top = stack_[0];
21955d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  stack_[0] = stack_[1];
22055d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  stack_[1] = stack_[2];
22155d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  stack_[2] = top;
22255d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  return true;
22355d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris}
22455d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris
22555d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferristemplate <typename AddressType>
22655d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferrisbool DwarfOp<AddressType>::op_abs() {
22755d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  SignedType signed_value = static_cast<SignedType>(stack_[0]);
22855d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  if (signed_value < 0) {
22955d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris    signed_value = -signed_value;
23055d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  }
23155d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  stack_[0] = static_cast<AddressType>(signed_value);
23255d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  return true;
23355d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris}
23455d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris
23555d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferristemplate <typename AddressType>
23655d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferrisbool DwarfOp<AddressType>::op_and() {
23755d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  AddressType top = StackPop();
23855d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  stack_[0] &= top;
23955d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  return true;
24055d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris}
24155d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris
24255d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferristemplate <typename AddressType>
24355d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferrisbool DwarfOp<AddressType>::op_div() {
24455d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  AddressType top = StackPop();
24555d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  if (top == 0) {
24655d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris    last_error_ = DWARF_ERROR_ILLEGAL_VALUE;
24755d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris    return false;
24855d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  }
24955d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  SignedType signed_divisor = static_cast<SignedType>(top);
25055d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  SignedType signed_dividend = static_cast<SignedType>(stack_[0]);
25155d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  stack_[0] = static_cast<AddressType>(signed_dividend / signed_divisor);
25255d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  return true;
25355d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris}
25455d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris
25555d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferristemplate <typename AddressType>
25655d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferrisbool DwarfOp<AddressType>::op_minus() {
25755d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  AddressType top = StackPop();
25855d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  stack_[0] -= top;
25955d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  return true;
26055d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris}
26155d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris
26255d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferristemplate <typename AddressType>
26355d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferrisbool DwarfOp<AddressType>::op_mod() {
26455d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  AddressType top = StackPop();
26555d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  if (top == 0) {
26655d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris    last_error_ = DWARF_ERROR_ILLEGAL_VALUE;
26755d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris    return false;
26855d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  }
26955d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  stack_[0] %= top;
27055d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  return true;
27155d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris}
27255d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris
27355d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferristemplate <typename AddressType>
27455d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferrisbool DwarfOp<AddressType>::op_mul() {
27555d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  AddressType top = StackPop();
27655d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  stack_[0] *= top;
27755d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  return true;
27855d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris}
27955d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris
28055d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferristemplate <typename AddressType>
28155d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferrisbool DwarfOp<AddressType>::op_neg() {
28255d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  SignedType signed_value = static_cast<SignedType>(stack_[0]);
28355d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  stack_[0] = static_cast<AddressType>(-signed_value);
28455d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  return true;
28555d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris}
28655d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris
28755d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferristemplate <typename AddressType>
28855d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferrisbool DwarfOp<AddressType>::op_not() {
28955d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  stack_[0] = ~stack_[0];
29055d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  return true;
29155d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris}
29255d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris
29355d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferristemplate <typename AddressType>
29455d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferrisbool DwarfOp<AddressType>::op_or() {
29555d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  AddressType top = StackPop();
29655d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  stack_[0] |= top;
29755d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  return true;
29855d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris}
29955d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris
30055d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferristemplate <typename AddressType>
30155d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferrisbool DwarfOp<AddressType>::op_plus() {
30255d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  AddressType top = StackPop();
30355d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  stack_[0] += top;
30455d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  return true;
30555d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris}
30655d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris
30755d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferristemplate <typename AddressType>
30855d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferrisbool DwarfOp<AddressType>::op_plus_uconst() {
30955d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  stack_[0] += OperandAt(0);
31055d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  return true;
31155d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris}
31255d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris
31355d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferristemplate <typename AddressType>
31455d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferrisbool DwarfOp<AddressType>::op_shl() {
31555d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  AddressType top = StackPop();
31655d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  stack_[0] <<= top;
31755d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  return true;
31855d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris}
31955d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris
32055d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferristemplate <typename AddressType>
32155d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferrisbool DwarfOp<AddressType>::op_shr() {
32255d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  AddressType top = StackPop();
32355d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  stack_[0] >>= top;
32455d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  return true;
32555d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris}
32655d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris
32755d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferristemplate <typename AddressType>
32855d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferrisbool DwarfOp<AddressType>::op_shra() {
32955d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  AddressType top = StackPop();
33055d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  SignedType signed_value = static_cast<SignedType>(stack_[0]) >> top;
33155d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  stack_[0] = static_cast<AddressType>(signed_value);
33255d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  return true;
33355d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris}
33455d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris
33555d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferristemplate <typename AddressType>
33655d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferrisbool DwarfOp<AddressType>::op_xor() {
33755d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  AddressType top = StackPop();
33855d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  stack_[0] ^= top;
33955d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  return true;
34055d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris}
34155d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris
34255d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferristemplate <typename AddressType>
34355d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferrisbool DwarfOp<AddressType>::op_bra() {
34455d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  // Requires one stack element.
34555d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  AddressType top = StackPop();
34655d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  int16_t offset = static_cast<int16_t>(OperandAt(0));
34755d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  uint64_t cur_offset;
34855d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  if (top != 0) {
34955d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris    cur_offset = memory_->cur_offset() + offset;
35055d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  } else {
35155d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris    cur_offset = memory_->cur_offset() - offset;
35255d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  }
35355d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  memory_->set_cur_offset(cur_offset);
35455d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  return true;
35555d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris}
35655d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris
35755d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferristemplate <typename AddressType>
35855d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferrisbool DwarfOp<AddressType>::op_eq() {
35955d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  AddressType top = StackPop();
36055d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  stack_[0] = bool_to_dwarf_bool(stack_[0] == top);
36155d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  return true;
36255d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris}
36355d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris
36455d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferristemplate <typename AddressType>
36555d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferrisbool DwarfOp<AddressType>::op_ge() {
36655d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  AddressType top = StackPop();
36755d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  stack_[0] = bool_to_dwarf_bool(stack_[0] >= top);
36855d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  return true;
36955d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris}
37055d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris
37155d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferristemplate <typename AddressType>
37255d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferrisbool DwarfOp<AddressType>::op_gt() {
37355d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  AddressType top = StackPop();
37455d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  stack_[0] = bool_to_dwarf_bool(stack_[0] > top);
37555d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  return true;
37655d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris}
37755d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris
37855d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferristemplate <typename AddressType>
37955d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferrisbool DwarfOp<AddressType>::op_le() {
38055d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  AddressType top = StackPop();
38155d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  stack_[0] = bool_to_dwarf_bool(stack_[0] <= top);
38255d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  return true;
38355d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris}
38455d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris
38555d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferristemplate <typename AddressType>
38655d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferrisbool DwarfOp<AddressType>::op_lt() {
38755d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  AddressType top = StackPop();
38855d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  stack_[0] = bool_to_dwarf_bool(stack_[0] < top);
38955d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  return true;
39055d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris}
39155d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris
39255d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferristemplate <typename AddressType>
39355d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferrisbool DwarfOp<AddressType>::op_ne() {
39455d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  AddressType top = StackPop();
39555d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  stack_[0] = bool_to_dwarf_bool(stack_[0] != top);
39655d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  return true;
39755d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris}
39855d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris
39955d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferristemplate <typename AddressType>
40055d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferrisbool DwarfOp<AddressType>::op_skip() {
40155d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  int16_t offset = static_cast<int16_t>(OperandAt(0));
40255d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  uint64_t cur_offset = memory_->cur_offset() + offset;
40355d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  memory_->set_cur_offset(cur_offset);
40455d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  return true;
40555d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris}
40655d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris
40755d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferristemplate <typename AddressType>
40855d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferrisbool DwarfOp<AddressType>::op_lit() {
40955d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  stack_.push_front(cur_op() - 0x30);
41055d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  return true;
41155d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris}
41255d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris
41355d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferristemplate <typename AddressType>
41455d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferrisbool DwarfOp<AddressType>::op_reg() {
41555d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  is_register_ = true;
41655d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  stack_.push_front(cur_op() - 0x50);
41755d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  return true;
41855d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris}
41955d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris
42055d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferristemplate <typename AddressType>
42155d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferrisbool DwarfOp<AddressType>::op_regx() {
42255d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  is_register_ = true;
42355d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  stack_.push_front(OperandAt(0));
42455d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  return true;
42555d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris}
42655d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris
42755d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris// It's not clear for breg/bregx, if this op should read the current
42855d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris// value of the register, or where we think that register is located.
42955d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris// For simplicity, the code will read the value before doing the unwind.
43055d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferristemplate <typename AddressType>
43155d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferrisbool DwarfOp<AddressType>::op_breg() {
43255d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  uint16_t reg = cur_op() - 0x70;
43355d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  if (reg >= regs_->total_regs()) {
43455d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris    last_error_ = DWARF_ERROR_ILLEGAL_VALUE;
43555d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris    return false;
43655d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  }
43755d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  stack_.push_front((*regs_)[reg] + OperandAt(0));
43855d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  return true;
43955d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris}
44055d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris
44155d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferristemplate <typename AddressType>
44255d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferrisbool DwarfOp<AddressType>::op_bregx() {
44355d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  AddressType reg = OperandAt(0);
44455d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  if (reg >= regs_->total_regs()) {
44555d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris    last_error_ = DWARF_ERROR_ILLEGAL_VALUE;
44655d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris    return false;
44755d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  }
44855d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  stack_.push_front((*regs_)[reg] + OperandAt(1));
44955d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  return true;
45055d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris}
45155d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris
45255d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferristemplate <typename AddressType>
45355d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferrisbool DwarfOp<AddressType>::op_nop() {
45455d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  return true;
45555d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris}
45655d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris
45755d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferristemplate <typename AddressType>
45855d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferrisbool DwarfOp<AddressType>::op_not_implemented() {
45955d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  last_error_ = DWARF_ERROR_NOT_IMPLEMENTED;
46055d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris  return false;
46155d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris}
46255d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris
46355d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferris// Explicitly instantiate DwarfOp.
46455d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferristemplate class DwarfOp<uint32_t>;
46555d22ef67c428a3f0994ee7da51b33c79ddcc552Christopher Ferristemplate class DwarfOp<uint64_t>;
466d226a5140989f509a0ed3e2723f05d5fc93ce8dfChristopher Ferris
467d226a5140989f509a0ed3e2723f05d5fc93ce8dfChristopher Ferris}  // namespace unwindstack
468