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