/*
 * Copyright (C) 2016 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/MachineX86_64.h>
#include <unwindstack/MapInfo.h>
#include <unwindstack/Memory.h>
#include <unwindstack/RegsX86_64.h>
#include <unwindstack/UcontextX86_64.h>
#include <unwindstack/UserX86_64.h>

namespace unwindstack {

RegsX86_64::RegsX86_64() : RegsImpl<uint64_t>(X86_64_REG_LAST, Location(LOCATION_SP_OFFSET, -8)) {}

ArchEnum RegsX86_64::Arch() {
  return ARCH_X86_64;
}

uint64_t RegsX86_64::pc() {
  return regs_[X86_64_REG_PC];
}

uint64_t RegsX86_64::sp() {
  return regs_[X86_64_REG_SP];
}

void RegsX86_64::set_pc(uint64_t pc) {
  regs_[X86_64_REG_PC] = pc;
}

void RegsX86_64::set_sp(uint64_t sp) {
  regs_[X86_64_REG_SP] = sp;
}

uint64_t RegsX86_64::GetPcAdjustment(uint64_t rel_pc, Elf*) {
  if (rel_pc == 0) {
    return 0;
  }
  return 1;
}

bool RegsX86_64::SetPcFromReturnAddress(Memory* process_memory) {
  // Attempt to get the return address from the top of the stack.
  uint64_t new_pc;
  if (!process_memory->ReadFully(regs_[X86_64_REG_SP], &new_pc, sizeof(new_pc)) ||
      new_pc == regs_[X86_64_REG_PC]) {
    return false;
  }

  regs_[X86_64_REG_PC] = new_pc;
  return true;
}

void RegsX86_64::IterateRegisters(std::function<void(const char*, uint64_t)> fn) {
  if (IsDefined(X86_64_REG_RAX))
    fn("rax", regs_[X86_64_REG_RAX]);
  if (IsDefined(X86_64_REG_RBX))
    fn("rbx", regs_[X86_64_REG_RBX]);
  if (IsDefined(X86_64_REG_RCX))
    fn("rcx", regs_[X86_64_REG_RCX]);
  if (IsDefined(X86_64_REG_RDX))
    fn("rdx", regs_[X86_64_REG_RDX]);
  if (IsDefined(X86_64_REG_R8))
    fn("r8", regs_[X86_64_REG_R8]);
  if (IsDefined(X86_64_REG_R9))
    fn("r9", regs_[X86_64_REG_R9]);
  if (IsDefined(X86_64_REG_R10))
    fn("r10", regs_[X86_64_REG_R10]);
  if (IsDefined(X86_64_REG_R11))
    fn("r11", regs_[X86_64_REG_R11]);
  if (IsDefined(X86_64_REG_R12))
    fn("r12", regs_[X86_64_REG_R12]);
  if (IsDefined(X86_64_REG_R13))
    fn("r13", regs_[X86_64_REG_R13]);
  if (IsDefined(X86_64_REG_R14))
    fn("r14", regs_[X86_64_REG_R14]);
  if (IsDefined(X86_64_REG_R15))
    fn("r15", regs_[X86_64_REG_R15]);
  if (IsDefined(X86_64_REG_RDI))
    fn("rdi", regs_[X86_64_REG_RDI]);
  if (IsDefined(X86_64_REG_RSI))
    fn("rsi", regs_[X86_64_REG_RSI]);
  if (IsDefined(X86_64_REG_RBP))
    fn("rbp", regs_[X86_64_REG_RBP]);
  if (IsDefined(X86_64_REG_RSP))
    fn("rsp", regs_[X86_64_REG_RSP]);
  if (IsDefined(X86_64_REG_RIP))
    fn("rip", regs_[X86_64_REG_RIP]);
}

Regs* RegsX86_64::Read(void* remote_data) {
  x86_64_user_regs* user = reinterpret_cast<x86_64_user_regs*>(remote_data);

  RegsX86_64* regs = new RegsX86_64();
  (*regs)[X86_64_REG_RAX] = user->rax;
  (*regs)[X86_64_REG_RBX] = user->rbx;
  (*regs)[X86_64_REG_RCX] = user->rcx;
  (*regs)[X86_64_REG_RDX] = user->rdx;
  (*regs)[X86_64_REG_R8] = user->r8;
  (*regs)[X86_64_REG_R9] = user->r9;
  (*regs)[X86_64_REG_R10] = user->r10;
  (*regs)[X86_64_REG_R11] = user->r11;
  (*regs)[X86_64_REG_R12] = user->r12;
  (*regs)[X86_64_REG_R13] = user->r13;
  (*regs)[X86_64_REG_R14] = user->r14;
  (*regs)[X86_64_REG_R15] = user->r15;
  (*regs)[X86_64_REG_RDI] = user->rdi;
  (*regs)[X86_64_REG_RSI] = user->rsi;
  (*regs)[X86_64_REG_RBP] = user->rbp;
  (*regs)[X86_64_REG_RSP] = user->rsp;
  (*regs)[X86_64_REG_RIP] = user->rip;

  return regs;
}

void RegsX86_64::SetFromUcontext(x86_64_ucontext_t* ucontext) {
  // R8-R15
  memcpy(&regs_[X86_64_REG_R8], &ucontext->uc_mcontext.r8, 8 * sizeof(uint64_t));

  // Rest of the registers.
  regs_[X86_64_REG_RDI] = ucontext->uc_mcontext.rdi;
  regs_[X86_64_REG_RSI] = ucontext->uc_mcontext.rsi;
  regs_[X86_64_REG_RBP] = ucontext->uc_mcontext.rbp;
  regs_[X86_64_REG_RBX] = ucontext->uc_mcontext.rbx;
  regs_[X86_64_REG_RDX] = ucontext->uc_mcontext.rdx;
  regs_[X86_64_REG_RAX] = ucontext->uc_mcontext.rax;
  regs_[X86_64_REG_RCX] = ucontext->uc_mcontext.rcx;
  regs_[X86_64_REG_RSP] = ucontext->uc_mcontext.rsp;
  regs_[X86_64_REG_RIP] = ucontext->uc_mcontext.rip;
}

Regs* RegsX86_64::CreateFromUcontext(void* ucontext) {
  x86_64_ucontext_t* x86_64_ucontext = reinterpret_cast<x86_64_ucontext_t*>(ucontext);

  RegsX86_64* regs = new RegsX86_64();
  regs->SetFromUcontext(x86_64_ucontext);
  return regs;
}

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

  uint16_t data2;
  if (!elf_memory->ReadFully(rel_pc + 8, &data2, sizeof(data2)) || data2 != 0x0f05) {
    return false;
  }

  // __restore_rt:
  // 0x48 0xc7 0xc0 0x0f 0x00 0x00 0x00   mov $0xf,%rax
  // 0x0f 0x05                            syscall
  // 0x0f                                 nopl 0x0($rax)

  // Read the mcontext data from the stack.
  // sp points to the ucontext data structure, read only the mcontext part.
  x86_64_ucontext_t x86_64_ucontext;
  if (!process_memory->ReadFully(regs_[X86_64_REG_SP] + 0x28, &x86_64_ucontext.uc_mcontext,
                                 sizeof(x86_64_mcontext_t))) {
    return false;
  }
  SetFromUcontext(&x86_64_ucontext);
  return true;
}

Regs* RegsX86_64::Clone() {
  return new RegsX86_64(*this);
}

}  // namespace unwindstack
