/*
 * 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 <functional>

#include <unwindstack/Elf.h>
#include <unwindstack/MapInfo.h>
#include <unwindstack/Memory.h>
#include <unwindstack/RegsMips.h>

#include "MachineMips.h"
#include "UcontextMips.h"
#include "UserMips.h"

namespace unwindstack {

RegsMips::RegsMips()
    : RegsImpl<uint32_t>(MIPS_REG_LAST, MIPS_REG_SP, Location(LOCATION_REGISTER, MIPS_REG_RA)) {}

ArchEnum RegsMips::Arch() {
  return ARCH_MIPS;
}

uint64_t RegsMips::GetAdjustedPc(uint64_t rel_pc, Elf* elf) {
  if (!elf->valid()) {
    return rel_pc;
  }

  // For now, just assuming no compact branches
  if (rel_pc < 8) {
    return rel_pc;
  }
  return rel_pc - 8;
}

void RegsMips::SetFromRaw() {
  set_pc(regs_[MIPS_REG_PC]);
  set_sp(regs_[MIPS_REG_SP]);
}

bool RegsMips::SetPcFromReturnAddress(Memory*) {
  if (pc() == regs_[MIPS_REG_RA]) {
    return false;
  }

  set_pc(regs_[MIPS_REG_RA]);
  return true;
}

void RegsMips::IterateRegisters(std::function<void(const char*, uint64_t)> fn) {
  fn("r0", regs_[MIPS_REG_R0]);
  fn("r1", regs_[MIPS_REG_R1]);
  fn("r2", regs_[MIPS_REG_R2]);
  fn("r3", regs_[MIPS_REG_R3]);
  fn("r4", regs_[MIPS_REG_R4]);
  fn("r5", regs_[MIPS_REG_R5]);
  fn("r6", regs_[MIPS_REG_R6]);
  fn("r7", regs_[MIPS_REG_R7]);
  fn("r8", regs_[MIPS_REG_R8]);
  fn("r9", regs_[MIPS_REG_R9]);
  fn("r10", regs_[MIPS_REG_R10]);
  fn("r11", regs_[MIPS_REG_R11]);
  fn("r12", regs_[MIPS_REG_R12]);
  fn("r13", regs_[MIPS_REG_R13]);
  fn("r14", regs_[MIPS_REG_R14]);
  fn("r15", regs_[MIPS_REG_R15]);
  fn("r16", regs_[MIPS_REG_R16]);
  fn("r17", regs_[MIPS_REG_R17]);
  fn("r18", regs_[MIPS_REG_R18]);
  fn("r19", regs_[MIPS_REG_R19]);
  fn("r20", regs_[MIPS_REG_R20]);
  fn("r21", regs_[MIPS_REG_R21]);
  fn("r22", regs_[MIPS_REG_R22]);
  fn("r23", regs_[MIPS_REG_R23]);
  fn("r24", regs_[MIPS_REG_R24]);
  fn("r25", regs_[MIPS_REG_R25]);
  fn("r26", regs_[MIPS_REG_R26]);
  fn("r27", regs_[MIPS_REG_R27]);
  fn("r28", regs_[MIPS_REG_R28]);
  fn("sp", regs_[MIPS_REG_SP]);
  fn("r30", regs_[MIPS_REG_R30]);
  fn("ra", regs_[MIPS_REG_RA]);
  fn("pc", regs_[MIPS_REG_PC]);
}

Regs* RegsMips::Read(void* remote_data) {
  mips_user_regs* user = reinterpret_cast<mips_user_regs*>(remote_data);
  RegsMips* regs = new RegsMips();
  uint32_t* reg_data = reinterpret_cast<uint32_t*>(regs->RawData());

  memcpy(regs->RawData(), &user->regs[MIPS32_EF_R0], (MIPS_REG_R31 + 1) * sizeof(uint32_t));

  reg_data[MIPS_REG_PC] = user->regs[MIPS32_EF_CP0_EPC];
  regs->SetFromRaw();
  return regs;
}

Regs* RegsMips::CreateFromUcontext(void* ucontext) {
  mips_ucontext_t* mips_ucontext = reinterpret_cast<mips_ucontext_t*>(ucontext);

  RegsMips* regs = new RegsMips();
  // Copy 64 bit sc_regs over to 32 bit regs
  for (int i = 0; i < 32; i++) {
      (*regs)[MIPS_REG_R0 + i] = mips_ucontext->uc_mcontext.sc_regs[i];
  }
  (*regs)[MIPS_REG_PC] = mips_ucontext->uc_mcontext.sc_pc;
  regs->SetFromRaw();
  return regs;
}

bool RegsMips::StepIfSignalHandler(uint64_t rel_pc, Elf* elf, Memory* process_memory) {
  uint64_t data;
  uint64_t offset = 0;
  Memory* elf_memory = elf->memory();
  // Read from elf memory since it is usually more expensive to read from
  // process memory.
  if (!elf_memory->Read(rel_pc, &data, sizeof(data))) {
    return false;
  }

  // Look for the kernel sigreturn functions.
  // __vdso_rt_sigreturn:
  // 0x24021061     li  v0, 0x1061
  // 0x0000000c     syscall
  // __vdso_sigreturn:
  // 0x24021017     li  v0, 0x1017
  // 0x0000000c     syscall
  if (data == 0x0000000c24021061ULL) {
    // vdso_rt_sigreturn => read rt_sigframe
    // offset = siginfo offset + sizeof(siginfo) + uc_mcontext offset + sc_pc offset
    offset = 24 + 128 + 24 + 8;
  } else if (data == 0x0000000c24021017LL) {
    // vdso_sigreturn => read sigframe
    // offset = sigcontext offset + sc_pc offset
    offset = 24 + 8;
  } else {
    return false;
  }

  // read sc_pc and sc_regs[32] from stack
  uint64_t values[MIPS_REG_LAST];
  if (!process_memory->Read(sp() + offset, values, sizeof(values))) {
    return false;
  }

  // Copy 64 bit sc_pc over to 32 bit regs_[MIPS_REG_PC]
  regs_[MIPS_REG_PC] = values[0];

  // Copy 64 bit sc_regs over to 32 bit regs
  for (int i = 0; i < 32; i++) {
      regs_[MIPS_REG_R0 + i] = values[1 + i];
  }

  SetFromRaw();
  return true;
}

}  // namespace unwindstack
