/*
 * Copyright (C) 2017 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <stdint.h>

#include <deque>
#include <string>
#include <vector>

#include <android-base/stringprintf.h>

#include <unwindstack/DwarfMemory.h>
#include <unwindstack/Log.h>
#include <unwindstack/Memory.h>
#include <unwindstack/Regs.h>

#include "DwarfError.h"
#include "DwarfOp.h"

namespace unwindstack {

template <typename AddressType>
constexpr typename DwarfOp<AddressType>::OpCallback DwarfOp<AddressType>::kCallbackTable[256];

template <typename AddressType>
bool DwarfOp<AddressType>::Eval(uint64_t start, uint64_t end, uint8_t dwarf_version) {
  uint32_t iterations = 0;
  is_register_ = false;
  stack_.clear();
  memory_->set_cur_offset(start);
  while (memory_->cur_offset() < end) {
    if (!Decode(dwarf_version)) {
      return false;
    }
    // To protect against a branch that creates an infinite loop,
    // terminate if the number of iterations gets too high.
    if (iterations++ == 1000) {
      last_error_ = DWARF_ERROR_TOO_MANY_ITERATIONS;
      return false;
    }
  }
  return true;
}

template <typename AddressType>
bool DwarfOp<AddressType>::Decode(uint8_t dwarf_version) {
  last_error_ = DWARF_ERROR_NONE;
  if (!memory_->ReadBytes(&cur_op_, 1)) {
    last_error_ = DWARF_ERROR_MEMORY_INVALID;
    return false;
  }

  const auto* op = &kCallbackTable[cur_op_];
  const auto handle_func = op->handle_func;
  if (handle_func == nullptr) {
    last_error_ = DWARF_ERROR_ILLEGAL_VALUE;
    return false;
  }

  // Check for an unsupported opcode.
  if (dwarf_version < op->supported_version) {
    last_error_ = DWARF_ERROR_ILLEGAL_VALUE;
    return false;
  }

  // Make sure that the required number of stack elements is available.
  if (stack_.size() < op->num_required_stack_values) {
    last_error_ = DWARF_ERROR_STACK_INDEX_NOT_VALID;
    return false;
  }

  operands_.clear();
  for (size_t i = 0; i < op->num_operands; i++) {
    uint64_t value;
    if (!memory_->ReadEncodedValue<AddressType>(op->operands[i], &value)) {
      last_error_ = DWARF_ERROR_MEMORY_INVALID;
      return false;
    }
    operands_.push_back(value);
  }
  return (this->*handle_func)();
}

template <typename AddressType>
void DwarfOp<AddressType>::GetLogInfo(uint64_t start, uint64_t end,
                                      std::vector<std::string>* lines) {
  memory_->set_cur_offset(start);
  while (memory_->cur_offset() < end) {
    uint8_t cur_op;
    if (!memory_->ReadBytes(&cur_op, 1)) {
      return;
    }

    std::string raw_string(android::base::StringPrintf("Raw Data: 0x%02x", cur_op));
    std::string log_string;
    const auto* op = &kCallbackTable[cur_op];
    if (op->handle_func == nullptr) {
      log_string = "Illegal";
    } else {
      log_string = op->name;
      uint64_t start_offset = memory_->cur_offset();
      for (size_t i = 0; i < op->num_operands; i++) {
        uint64_t value;
        if (!memory_->ReadEncodedValue<AddressType>(op->operands[i], &value)) {
          return;
        }
        log_string += ' ' + std::to_string(value);
      }
      uint64_t end_offset = memory_->cur_offset();

      memory_->set_cur_offset(start_offset);
      for (size_t i = start_offset; i < end_offset; i++) {
        uint8_t byte;
        if (!memory_->ReadBytes(&byte, 1)) {
          return;
        }
        raw_string += android::base::StringPrintf(" 0x%02x", byte);
      }
      memory_->set_cur_offset(end_offset);
    }
    lines->push_back(std::move(log_string));
    lines->push_back(std::move(raw_string));
  }
}

template <typename AddressType>
bool DwarfOp<AddressType>::op_deref() {
  // Read the address and dereference it.
  AddressType addr = StackPop();
  AddressType value;
  if (!regular_memory()->Read(addr, &value, sizeof(value))) {
    last_error_ = DWARF_ERROR_MEMORY_INVALID;
    return false;
  }
  stack_.push_front(value);
  return true;
}

template <typename AddressType>
bool DwarfOp<AddressType>::op_deref_size() {
  AddressType bytes_to_read = OperandAt(0);
  if (bytes_to_read > sizeof(AddressType) || bytes_to_read == 0) {
    last_error_ = DWARF_ERROR_ILLEGAL_VALUE;
    return false;
  }
  // Read the address and dereference it.
  AddressType addr = StackPop();
  AddressType value = 0;
  if (!regular_memory()->Read(addr, &value, bytes_to_read)) {
    last_error_ = DWARF_ERROR_MEMORY_INVALID;
    return false;
  }
  stack_.push_front(value);
  return true;
}

template <typename AddressType>
bool DwarfOp<AddressType>::op_push() {
  // Push all of the operands.
  for (auto operand : operands_) {
    stack_.push_front(operand);
  }
  return true;
}

template <typename AddressType>
bool DwarfOp<AddressType>::op_dup() {
  stack_.push_front(StackAt(0));
  return true;
}

template <typename AddressType>
bool DwarfOp<AddressType>::op_drop() {
  StackPop();
  return true;
}

template <typename AddressType>
bool DwarfOp<AddressType>::op_over() {
  stack_.push_front(StackAt(1));
  return true;
}

template <typename AddressType>
bool DwarfOp<AddressType>::op_pick() {
  AddressType index = OperandAt(0);
  if (index > StackSize()) {
    last_error_ = DWARF_ERROR_STACK_INDEX_NOT_VALID;
    return false;
  }
  stack_.push_front(StackAt(index));
  return true;
}

template <typename AddressType>
bool DwarfOp<AddressType>::op_swap() {
  AddressType old_value = stack_[0];
  stack_[0] = stack_[1];
  stack_[1] = old_value;
  return true;
}

template <typename AddressType>
bool DwarfOp<AddressType>::op_rot() {
  AddressType top = stack_[0];
  stack_[0] = stack_[1];
  stack_[1] = stack_[2];
  stack_[2] = top;
  return true;
}

template <typename AddressType>
bool DwarfOp<AddressType>::op_abs() {
  SignedType signed_value = static_cast<SignedType>(stack_[0]);
  if (signed_value < 0) {
    signed_value = -signed_value;
  }
  stack_[0] = static_cast<AddressType>(signed_value);
  return true;
}

template <typename AddressType>
bool DwarfOp<AddressType>::op_and() {
  AddressType top = StackPop();
  stack_[0] &= top;
  return true;
}

template <typename AddressType>
bool DwarfOp<AddressType>::op_div() {
  AddressType top = StackPop();
  if (top == 0) {
    last_error_ = DWARF_ERROR_ILLEGAL_VALUE;
    return false;
  }
  SignedType signed_divisor = static_cast<SignedType>(top);
  SignedType signed_dividend = static_cast<SignedType>(stack_[0]);
  stack_[0] = static_cast<AddressType>(signed_dividend / signed_divisor);
  return true;
}

template <typename AddressType>
bool DwarfOp<AddressType>::op_minus() {
  AddressType top = StackPop();
  stack_[0] -= top;
  return true;
}

template <typename AddressType>
bool DwarfOp<AddressType>::op_mod() {
  AddressType top = StackPop();
  if (top == 0) {
    last_error_ = DWARF_ERROR_ILLEGAL_VALUE;
    return false;
  }
  stack_[0] %= top;
  return true;
}

template <typename AddressType>
bool DwarfOp<AddressType>::op_mul() {
  AddressType top = StackPop();
  stack_[0] *= top;
  return true;
}

template <typename AddressType>
bool DwarfOp<AddressType>::op_neg() {
  SignedType signed_value = static_cast<SignedType>(stack_[0]);
  stack_[0] = static_cast<AddressType>(-signed_value);
  return true;
}

template <typename AddressType>
bool DwarfOp<AddressType>::op_not() {
  stack_[0] = ~stack_[0];
  return true;
}

template <typename AddressType>
bool DwarfOp<AddressType>::op_or() {
  AddressType top = StackPop();
  stack_[0] |= top;
  return true;
}

template <typename AddressType>
bool DwarfOp<AddressType>::op_plus() {
  AddressType top = StackPop();
  stack_[0] += top;
  return true;
}

template <typename AddressType>
bool DwarfOp<AddressType>::op_plus_uconst() {
  stack_[0] += OperandAt(0);
  return true;
}

template <typename AddressType>
bool DwarfOp<AddressType>::op_shl() {
  AddressType top = StackPop();
  stack_[0] <<= top;
  return true;
}

template <typename AddressType>
bool DwarfOp<AddressType>::op_shr() {
  AddressType top = StackPop();
  stack_[0] >>= top;
  return true;
}

template <typename AddressType>
bool DwarfOp<AddressType>::op_shra() {
  AddressType top = StackPop();
  SignedType signed_value = static_cast<SignedType>(stack_[0]) >> top;
  stack_[0] = static_cast<AddressType>(signed_value);
  return true;
}

template <typename AddressType>
bool DwarfOp<AddressType>::op_xor() {
  AddressType top = StackPop();
  stack_[0] ^= top;
  return true;
}

template <typename AddressType>
bool DwarfOp<AddressType>::op_bra() {
  // Requires one stack element.
  AddressType top = StackPop();
  int16_t offset = static_cast<int16_t>(OperandAt(0));
  uint64_t cur_offset;
  if (top != 0) {
    cur_offset = memory_->cur_offset() + offset;
  } else {
    cur_offset = memory_->cur_offset() - offset;
  }
  memory_->set_cur_offset(cur_offset);
  return true;
}

template <typename AddressType>
bool DwarfOp<AddressType>::op_eq() {
  AddressType top = StackPop();
  stack_[0] = bool_to_dwarf_bool(stack_[0] == top);
  return true;
}

template <typename AddressType>
bool DwarfOp<AddressType>::op_ge() {
  AddressType top = StackPop();
  stack_[0] = bool_to_dwarf_bool(stack_[0] >= top);
  return true;
}

template <typename AddressType>
bool DwarfOp<AddressType>::op_gt() {
  AddressType top = StackPop();
  stack_[0] = bool_to_dwarf_bool(stack_[0] > top);
  return true;
}

template <typename AddressType>
bool DwarfOp<AddressType>::op_le() {
  AddressType top = StackPop();
  stack_[0] = bool_to_dwarf_bool(stack_[0] <= top);
  return true;
}

template <typename AddressType>
bool DwarfOp<AddressType>::op_lt() {
  AddressType top = StackPop();
  stack_[0] = bool_to_dwarf_bool(stack_[0] < top);
  return true;
}

template <typename AddressType>
bool DwarfOp<AddressType>::op_ne() {
  AddressType top = StackPop();
  stack_[0] = bool_to_dwarf_bool(stack_[0] != top);
  return true;
}

template <typename AddressType>
bool DwarfOp<AddressType>::op_skip() {
  int16_t offset = static_cast<int16_t>(OperandAt(0));
  uint64_t cur_offset = memory_->cur_offset() + offset;
  memory_->set_cur_offset(cur_offset);
  return true;
}

template <typename AddressType>
bool DwarfOp<AddressType>::op_lit() {
  stack_.push_front(cur_op() - 0x30);
  return true;
}

template <typename AddressType>
bool DwarfOp<AddressType>::op_reg() {
  is_register_ = true;
  stack_.push_front(cur_op() - 0x50);
  return true;
}

template <typename AddressType>
bool DwarfOp<AddressType>::op_regx() {
  is_register_ = true;
  stack_.push_front(OperandAt(0));
  return true;
}

// It's not clear for breg/bregx, if this op should read the current
// value of the register, or where we think that register is located.
// For simplicity, the code will read the value before doing the unwind.
template <typename AddressType>
bool DwarfOp<AddressType>::op_breg() {
  uint16_t reg = cur_op() - 0x70;
  if (reg >= regs_->total_regs()) {
    last_error_ = DWARF_ERROR_ILLEGAL_VALUE;
    return false;
  }
  stack_.push_front((*regs_)[reg] + OperandAt(0));
  return true;
}

template <typename AddressType>
bool DwarfOp<AddressType>::op_bregx() {
  AddressType reg = OperandAt(0);
  if (reg >= regs_->total_regs()) {
    last_error_ = DWARF_ERROR_ILLEGAL_VALUE;
    return false;
  }
  stack_.push_front((*regs_)[reg] + OperandAt(1));
  return true;
}

template <typename AddressType>
bool DwarfOp<AddressType>::op_nop() {
  return true;
}

template <typename AddressType>
bool DwarfOp<AddressType>::op_not_implemented() {
  last_error_ = DWARF_ERROR_NOT_IMPLEMENTED;
  return false;
}

// Explicitly instantiate DwarfOp.
template class DwarfOp<uint32_t>;
template class DwarfOp<uint64_t>;

}  // namespace unwindstack
