// Copyright 2016 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "thread.h"

#include <cinttypes>
#include <string>

#include <zircon/syscalls.h>
#include <zircon/syscalls/exception.h>

#include "lib/fxl/logging.h"
#include "lib/fxl/strings/string_printf.h"

#include "garnet/lib/debugger_utils/util.h"

#include "arch.h"
#include "process.h"
#include "server.h"

namespace inferior_control {

// static
const char* Thread::StateName(Thread::State state) {
#define CASE_TO_STR(x)   \
  case Thread::State::x: \
    return #x
  switch (state) {
    CASE_TO_STR(kNew);
    CASE_TO_STR(kStopped);
    CASE_TO_STR(kRunning);
    CASE_TO_STR(kStepping);
    CASE_TO_STR(kExiting);
    CASE_TO_STR(kGone);
    default:
      break;
  }
#undef CASE_TO_STR
  return "(unknown)";
}

Thread::Thread(Process* process, zx_handle_t handle, zx_koid_t id)
    : process_(process),
      handle_(handle),
      id_(id),
      state_(State::kNew),
      breakpoints_(this),
      weak_ptr_factory_(this) {
  FXL_DCHECK(process_);
  FXL_DCHECK(handle_ != ZX_HANDLE_INVALID);
  FXL_DCHECK(id_ != ZX_KOID_INVALID);

  registers_ = Registers::Create(this);
  FXL_DCHECK(registers_.get());
}

Thread::~Thread() {
  FXL_VLOG(2) << "Destructing thread " << GetDebugName();

  Clear();
}

std::string Thread::GetName() const {
  return fxl::StringPrintf("%" PRId64 ".%" PRId64, process_->id(), id());
}

std::string Thread::GetDebugName() const {
  return fxl::StringPrintf("%" PRId64 ".%" PRId64 "(%" PRIx64 ".%" PRIx64 ")",
                           process_->id(), id(), process_->id(), id());
}

void Thread::set_state(State state) {
  FXL_DCHECK(state != State::kNew);
  state_ = state;
}

bool Thread::IsLive() const {
  switch (state_) {
    case State::kNew:
    case State::kStopped:
    case State::kRunning:
    case State::kStepping:
      return true;
    default:
      return false;
  }
}

void Thread::Clear() {
  // We close the handle here so the o/s will release the thread.
  if (handle_ != ZX_HANDLE_INVALID)
    zx_handle_close(handle_);
  handle_ = ZX_HANDLE_INVALID;
}

zx_handle_t Thread::GetExceptionPortHandle() {
  return process_->server()->exception_port().GetUnownedExceptionPort()->get();
}

fxl::WeakPtr<Thread> Thread::AsWeakPtr() {
  return weak_ptr_factory_.GetWeakPtr();
}

GdbSignal Thread::GetGdbSignal() const {
  if (!exception_context_) {
    // TODO(dje): kNone may be a better value to return here.
    return GdbSignal::kUnsupported;
  }

  return ComputeGdbSignal(*exception_context_);
}

void Thread::OnException(const zx_excp_type_t type,
                         const zx_exception_context_t& context) {
  // TODO(dje): While having a pointer allows for a simple "do we have a
  // context" check, it might be simpler to just store the struct in the class.
  exception_context_.reset(new zx_exception_context_t);
  *exception_context_ = context;

  State prev_state = state_;
  set_state(State::kStopped);

  // If we were singlestepping turn it off.
  // If the user wants to try the singlestep again it must be re-requested.
  // If the thread has exited we may not be able to, and there's no point
  // anyway.
  if (prev_state == State::kStepping && type != ZX_EXCP_THREAD_EXITING) {
    FXL_DCHECK(breakpoints_.SingleStepBreakpointInserted());
    if (!breakpoints_.RemoveSingleStepBreakpoint()) {
      FXL_LOG(ERROR) << "Unable to clear single-step bkpt";
    } else {
      FXL_VLOG(2) << "Single-step bkpt cleared";
    }
  }
}

bool Thread::Resume() {
  if (state() != State::kStopped && state() != State::kNew) {
    FXL_LOG(ERROR) << "Cannot resume a thread while in state: "
                   << StateName(state());
    return false;
  }

  // This is printed here before resuming the task so that this is always
  // printed before any subsequent exception report (which is read by another
  // thread).
  FXL_VLOG(2) << "Thread " << GetName() << " is now running";

  zx_status_t status =
      zx_task_resume_from_exception(handle_, GetExceptionPortHandle(), 0);
  if (status < 0) {
    FXL_LOG(ERROR) << "Failed to resume thread: "
                   << debugger_utils::ZxErrorString(status);
    return false;
  }

  state_ = State::kRunning;
  return true;
}

void Thread::ResumeForExit() {
  switch (state()) {
    case State::kNew:
    case State::kStopped:
    case State::kExiting:
      break;
    default:
      FXL_DCHECK(false) << "unexpected state " << StateName(state());
      break;
  }

  FXL_VLOG(2) << "Thread " << GetName() << " is exiting";

  auto status =
      zx_task_resume_from_exception(handle_, GetExceptionPortHandle(), 0);
  if (status < 0) {
    // This might fail if the process has been killed in the interim.
    // It shouldn't otherwise fail. Just log the failure, nothing else
    // we can do.
    zx_info_process_t info;
    auto info_status =
        zx_object_get_info(process()->handle(), ZX_INFO_PROCESS, &info,
                           sizeof(info), nullptr, nullptr);
    if (info_status != ZX_OK) {
      FXL_LOG(ERROR) << "error getting process info: "
                     << debugger_utils::ZxErrorString(info_status);
    }
    if (info_status == ZX_OK && info.exited) {
      FXL_VLOG(2) << "Process " << process()->GetName() << " exited too";
    } else {
      FXL_LOG(ERROR) << "Failed to resume thread for exit: "
                     << debugger_utils::ZxErrorString(status);
    }
  }

  set_state(State::kGone);
  Clear();
}

bool Thread::Step() {
  if (state() != State::kStopped) {
    FXL_LOG(ERROR) << "Cannot resume a thread while in state: "
                   << StateName(state());
    return false;
  }

  if (!registers_->RefreshGeneralRegisters()) {
    FXL_LOG(ERROR) << "Failed refreshing gregs";
    return false;
  }
  zx_vaddr_t pc = registers_->GetPC();

  if (!breakpoints_.InsertSingleStepBreakpoint(pc))
    return false;

  // This is printed here before resuming the task so that this is always
  // printed before any subsequent exception report (which is read by another
  // thread).
  FXL_LOG(INFO) << "Thread " << GetName() << " is now stepping";

  zx_status_t status =
      zx_task_resume_from_exception(handle_, GetExceptionPortHandle(), 0);
  if (status < 0) {
    breakpoints_.RemoveSingleStepBreakpoint();
    FXL_LOG(ERROR) << "Failed to resume thread for step: "
                   << debugger_utils::ZxErrorString(status);
    return false;
  }

  state_ = State::kStepping;
  return true;
}

}  // namespace inferior_control
