//===-- NativeThreadLinux.cpp --------------------------------- -*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#include "NativeThreadLinux.h"

#include <signal.h>
#include <sstream>

#include "NativeProcessLinux.h"
#include "NativeRegisterContextLinux.h"
#include "SingleStepCheck.h"

#include "lldb/Host/HostNativeThread.h"
#include "lldb/Host/linux/Ptrace.h"
#include "lldb/Host/linux/Support.h"
#include "lldb/Utility/LLDBAssert.h"
#include "lldb/Utility/Log.h"
#include "lldb/Utility/State.h"
#include "lldb/lldb-enumerations.h"

#include "llvm/ADT/SmallString.h"

#include "Plugins/Process/POSIX/CrashReason.h"

#include <sys/syscall.h>
// Try to define a macro to encapsulate the tgkill syscall
#define tgkill(pid, tid, sig)                                                  \
  syscall(__NR_tgkill, static_cast<::pid_t>(pid), static_cast<::pid_t>(tid),   \
          sig)

using namespace lldb;
using namespace lldb_private;
using namespace lldb_private::process_linux;

namespace {
void LogThreadStopInfo(Log &log, const ThreadStopInfo &stop_info,
                       const char *const header) {
  switch (stop_info.reason) {
  case eStopReasonNone:
    log.Printf("%s: %s no stop reason", __FUNCTION__, header);
    return;
  case eStopReasonTrace:
    log.Printf("%s: %s trace, stopping signal 0x%" PRIx32, __FUNCTION__, header,
               stop_info.details.signal.signo);
    return;
  case eStopReasonBreakpoint:
    log.Printf("%s: %s breakpoint, stopping signal 0x%" PRIx32, __FUNCTION__,
               header, stop_info.details.signal.signo);
    return;
  case eStopReasonWatchpoint:
    log.Printf("%s: %s watchpoint, stopping signal 0x%" PRIx32, __FUNCTION__,
               header, stop_info.details.signal.signo);
    return;
  case eStopReasonSignal:
    log.Printf("%s: %s signal 0x%02" PRIx32, __FUNCTION__, header,
               stop_info.details.signal.signo);
    return;
  case eStopReasonException:
    log.Printf("%s: %s exception type 0x%02" PRIx64, __FUNCTION__, header,
               stop_info.details.exception.type);
    return;
  case eStopReasonExec:
    log.Printf("%s: %s exec, stopping signal 0x%" PRIx32, __FUNCTION__, header,
               stop_info.details.signal.signo);
    return;
  case eStopReasonPlanComplete:
    log.Printf("%s: %s plan complete", __FUNCTION__, header);
    return;
  case eStopReasonThreadExiting:
    log.Printf("%s: %s thread exiting", __FUNCTION__, header);
    return;
  case eStopReasonInstrumentation:
    log.Printf("%s: %s instrumentation", __FUNCTION__, header);
    return;
  default:
    log.Printf("%s: %s invalid stop reason %" PRIu32, __FUNCTION__, header,
               static_cast<uint32_t>(stop_info.reason));
  }
}
}

NativeThreadLinux::NativeThreadLinux(NativeProcessLinux &process,
                                     lldb::tid_t tid)
    : NativeThreadProtocol(process, tid), m_state(StateType::eStateInvalid),
      m_stop_info(),
      m_reg_context_up(
          NativeRegisterContextLinux::CreateHostNativeRegisterContextLinux(
              process.GetArchitecture(), *this)),
      m_stop_description() {}

std::string NativeThreadLinux::GetName() {
  NativeProcessLinux &process = GetProcess();

  auto BufferOrError = getProcFile(process.GetID(), GetID(), "comm");
  if (!BufferOrError)
    return "";
  return BufferOrError.get()->getBuffer().rtrim('\n');
}

lldb::StateType NativeThreadLinux::GetState() { return m_state; }

bool NativeThreadLinux::GetStopReason(ThreadStopInfo &stop_info,
                                      std::string &description) {
  Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_THREAD));

  description.clear();

  switch (m_state) {
  case eStateStopped:
  case eStateCrashed:
  case eStateExited:
  case eStateSuspended:
  case eStateUnloaded:
    if (log)
      LogThreadStopInfo(*log, m_stop_info, "m_stop_info in thread:");
    stop_info = m_stop_info;
    description = m_stop_description;
    if (log)
      LogThreadStopInfo(*log, stop_info, "returned stop_info:");

    return true;

  case eStateInvalid:
  case eStateConnected:
  case eStateAttaching:
  case eStateLaunching:
  case eStateRunning:
  case eStateStepping:
  case eStateDetached:
    if (log) {
      LLDB_LOGF(log,
                "NativeThreadLinux::%s tid %" PRIu64
                " in state %s cannot answer stop reason",
                __FUNCTION__, GetID(), StateAsCString(m_state));
    }
    return false;
  }
  llvm_unreachable("unhandled StateType!");
}

Status NativeThreadLinux::SetWatchpoint(lldb::addr_t addr, size_t size,
                                        uint32_t watch_flags, bool hardware) {
  if (!hardware)
    return Status("not implemented");
  if (m_state == eStateLaunching)
    return Status();
  Status error = RemoveWatchpoint(addr);
  if (error.Fail())
    return error;
  uint32_t wp_index =
      m_reg_context_up->SetHardwareWatchpoint(addr, size, watch_flags);
  if (wp_index == LLDB_INVALID_INDEX32)
    return Status("Setting hardware watchpoint failed.");
  m_watchpoint_index_map.insert({addr, wp_index});
  return Status();
}

Status NativeThreadLinux::RemoveWatchpoint(lldb::addr_t addr) {
  auto wp = m_watchpoint_index_map.find(addr);
  if (wp == m_watchpoint_index_map.end())
    return Status();
  uint32_t wp_index = wp->second;
  m_watchpoint_index_map.erase(wp);
  if (m_reg_context_up->ClearHardwareWatchpoint(wp_index))
    return Status();
  return Status("Clearing hardware watchpoint failed.");
}

Status NativeThreadLinux::SetHardwareBreakpoint(lldb::addr_t addr,
                                                size_t size) {
  if (m_state == eStateLaunching)
    return Status();

  Status error = RemoveHardwareBreakpoint(addr);
  if (error.Fail())
    return error;

  uint32_t bp_index = m_reg_context_up->SetHardwareBreakpoint(addr, size);

  if (bp_index == LLDB_INVALID_INDEX32)
    return Status("Setting hardware breakpoint failed.");

  m_hw_break_index_map.insert({addr, bp_index});
  return Status();
}

Status NativeThreadLinux::RemoveHardwareBreakpoint(lldb::addr_t addr) {
  auto bp = m_hw_break_index_map.find(addr);
  if (bp == m_hw_break_index_map.end())
    return Status();

  uint32_t bp_index = bp->second;
  if (m_reg_context_up->ClearHardwareBreakpoint(bp_index)) {
    m_hw_break_index_map.erase(bp);
    return Status();
  }

  return Status("Clearing hardware breakpoint failed.");
}

Status NativeThreadLinux::Resume(uint32_t signo) {
  const StateType new_state = StateType::eStateRunning;
  MaybeLogStateChange(new_state);
  m_state = new_state;

  m_stop_info.reason = StopReason::eStopReasonNone;
  m_stop_description.clear();

  // If watchpoints have been set, but none on this thread, then this is a new
  // thread. So set all existing watchpoints.
  if (m_watchpoint_index_map.empty()) {
    NativeProcessLinux &process = GetProcess();

    const auto &watchpoint_map = process.GetWatchpointMap();
    m_reg_context_up->ClearAllHardwareWatchpoints();
    for (const auto &pair : watchpoint_map) {
      const auto &wp = pair.second;
      SetWatchpoint(wp.m_addr, wp.m_size, wp.m_watch_flags, wp.m_hardware);
    }
  }

  // Set all active hardware breakpoint on all threads.
  if (m_hw_break_index_map.empty()) {
    NativeProcessLinux &process = GetProcess();

    const auto &hw_breakpoint_map = process.GetHardwareBreakpointMap();
    m_reg_context_up->ClearAllHardwareBreakpoints();
    for (const auto &pair : hw_breakpoint_map) {
      const auto &bp = pair.second;
      SetHardwareBreakpoint(bp.m_addr, bp.m_size);
    }
  }

  intptr_t data = 0;

  if (signo != LLDB_INVALID_SIGNAL_NUMBER)
    data = signo;

  return NativeProcessLinux::PtraceWrapper(PTRACE_CONT, GetID(), nullptr,
                                           reinterpret_cast<void *>(data));
}

Status NativeThreadLinux::SingleStep(uint32_t signo) {
  const StateType new_state = StateType::eStateStepping;
  MaybeLogStateChange(new_state);
  m_state = new_state;
  m_stop_info.reason = StopReason::eStopReasonNone;

  if(!m_step_workaround) {
    // If we already hava a workaround inplace, don't reset it. Otherwise, the
    // destructor of the existing instance will run after the new instance has
    // fetched the cpu mask, and the thread will end up with the wrong mask.
    m_step_workaround = SingleStepWorkaround::Get(m_tid);
  }

  intptr_t data = 0;
  if (signo != LLDB_INVALID_SIGNAL_NUMBER)
    data = signo;

  // If hardware single-stepping is not supported, we just do a continue. The
  // breakpoint on the next instruction has been setup in
  // NativeProcessLinux::Resume.
  return NativeProcessLinux::PtraceWrapper(
      GetProcess().SupportHardwareSingleStepping() ? PTRACE_SINGLESTEP
                                                   : PTRACE_CONT,
      m_tid, nullptr, reinterpret_cast<void *>(data));
}

void NativeThreadLinux::SetStoppedBySignal(uint32_t signo,
                                           const siginfo_t *info) {
  Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_THREAD));
  LLDB_LOGF(log, "NativeThreadLinux::%s called with signal 0x%02" PRIx32,
            __FUNCTION__, signo);

  SetStopped();

  m_stop_info.reason = StopReason::eStopReasonSignal;
  m_stop_info.details.signal.signo = signo;

  m_stop_description.clear();
  if (info) {
    switch (signo) {
    case SIGSEGV:
    case SIGBUS:
    case SIGFPE:
    case SIGILL:
      // In case of MIPS64 target, SI_KERNEL is generated for invalid 64bit
      // address.
      const auto reason =
          (info->si_signo == SIGBUS && info->si_code == SI_KERNEL)
              ? CrashReason::eInvalidAddress
              : GetCrashReason(*info);
      m_stop_description = GetCrashReasonString(reason, *info);
      break;
    }
  }
}

bool NativeThreadLinux::IsStopped(int *signo) {
  if (!StateIsStoppedState(m_state, false))
    return false;

  // If we are stopped by a signal, return the signo.
  if (signo && m_state == StateType::eStateStopped &&
      m_stop_info.reason == StopReason::eStopReasonSignal) {
    *signo = m_stop_info.details.signal.signo;
  }

  // Regardless, we are stopped.
  return true;
}

void NativeThreadLinux::SetStopped() {
  if (m_state == StateType::eStateStepping)
    m_step_workaround.reset();

  const StateType new_state = StateType::eStateStopped;
  MaybeLogStateChange(new_state);
  m_state = new_state;
  m_stop_description.clear();
}

void NativeThreadLinux::SetStoppedByExec() {
  Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_THREAD));
  LLDB_LOGF(log, "NativeThreadLinux::%s()", __FUNCTION__);

  SetStopped();

  m_stop_info.reason = StopReason::eStopReasonExec;
  m_stop_info.details.signal.signo = SIGSTOP;
}

void NativeThreadLinux::SetStoppedByBreakpoint() {
  SetStopped();

  m_stop_info.reason = StopReason::eStopReasonBreakpoint;
  m_stop_info.details.signal.signo = SIGTRAP;
  m_stop_description.clear();
}

void NativeThreadLinux::SetStoppedByWatchpoint(uint32_t wp_index) {
  SetStopped();

  lldbassert(wp_index != LLDB_INVALID_INDEX32 && "wp_index cannot be invalid");

  std::ostringstream ostr;
  ostr << m_reg_context_up->GetWatchpointAddress(wp_index) << " ";
  ostr << wp_index;

  /*
   * MIPS: Last 3bits of the watchpoint address are masked by the kernel. For
   * example:
   * 'n' is at 0x120010d00 and 'm' is 0x120010d04. When a watchpoint is set at
   * 'm', then
   * watch exception is generated even when 'n' is read/written. To handle this
   * case,
   * find the base address of the load/store instruction and append it in the
   * stop-info
   * packet.
  */
  ostr << " " << m_reg_context_up->GetWatchpointHitAddress(wp_index);

  m_stop_description = ostr.str();

  m_stop_info.reason = StopReason::eStopReasonWatchpoint;
  m_stop_info.details.signal.signo = SIGTRAP;
}

bool NativeThreadLinux::IsStoppedAtBreakpoint() {
  return GetState() == StateType::eStateStopped &&
         m_stop_info.reason == StopReason::eStopReasonBreakpoint;
}

bool NativeThreadLinux::IsStoppedAtWatchpoint() {
  return GetState() == StateType::eStateStopped &&
         m_stop_info.reason == StopReason::eStopReasonWatchpoint;
}

void NativeThreadLinux::SetStoppedByTrace() {
  SetStopped();

  m_stop_info.reason = StopReason::eStopReasonTrace;
  m_stop_info.details.signal.signo = SIGTRAP;
}

void NativeThreadLinux::SetStoppedWithNoReason() {
  SetStopped();

  m_stop_info.reason = StopReason::eStopReasonNone;
  m_stop_info.details.signal.signo = 0;
}

void NativeThreadLinux::SetExited() {
  const StateType new_state = StateType::eStateExited;
  MaybeLogStateChange(new_state);
  m_state = new_state;

  m_stop_info.reason = StopReason::eStopReasonThreadExiting;
}

Status NativeThreadLinux::RequestStop() {
  Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_THREAD));

  NativeProcessLinux &process = GetProcess();

  lldb::pid_t pid = process.GetID();
  lldb::tid_t tid = GetID();

  LLDB_LOGF(log,
            "NativeThreadLinux::%s requesting thread stop(pid: %" PRIu64
            ", tid: %" PRIu64 ")",
            __FUNCTION__, pid, tid);

  Status err;
  errno = 0;
  if (::tgkill(pid, tid, SIGSTOP) != 0) {
    err.SetErrorToErrno();
    LLDB_LOGF(log,
              "NativeThreadLinux::%s tgkill(%" PRIu64 ", %" PRIu64
              ", SIGSTOP) failed: %s",
              __FUNCTION__, pid, tid, err.AsCString());
  }

  return err;
}

void NativeThreadLinux::MaybeLogStateChange(lldb::StateType new_state) {
  Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_THREAD));
  // If we're not logging, we're done.
  if (!log)
    return;

  // If this is a state change to the same state, we're done.
  lldb::StateType old_state = m_state;
  if (new_state == old_state)
    return;

  LLDB_LOG(log, "pid={0}, tid={1}: changing from state {2} to {3}",
           m_process.GetID(), GetID(), old_state, new_state);
}

NativeProcessLinux &NativeThreadLinux::GetProcess() {
  return static_cast<NativeProcessLinux &>(m_process);
}
