//===-- NativeProcessWindows.cpp ------------------------------------------===//
//
// 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 "lldb/Host/windows/windows.h"
#include <dbghelp.h>
#include <excpt.h>
#include <pathcch.h>
#include <psapi.h>

#include "NativeProcessWindows.h"
#include "NativeThreadWindows.h"
#include "lldb/Host/FileSystem.h"
#include "lldb/Host/HostNativeProcessBase.h"
#include "lldb/Host/HostProcess.h"
#include "lldb/Host/ProcessLaunchInfo.h"
#include "lldb/Host/PseudoTerminal.h"
#include "lldb/Host/windows/AutoHandle.h"
#include "lldb/Host/windows/ConnectionConPTYWindows.h"
#include "lldb/Host/windows/HostThreadWindows.h"
#include "lldb/Host/windows/PathUtils.h"
#include "lldb/Host/windows/ProcessLauncherWindows.h"
#include "lldb/Host/windows/PseudoConsole.h"
#include "lldb/Target/MemoryRegionInfo.h"
#include "lldb/Target/Process.h"
#include "lldb/Utility/State.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/ConvertUTF.h"
#include "llvm/Support/Errc.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/Format.h"
#include "llvm/Support/Threading.h"
#include "llvm/Support/raw_ostream.h"

#include "DebuggerThread.h"
#include "ExceptionRecord.h"
#include "ProcessWindowsLog.h"

#include <tlhelp32.h>

#pragma warning(disable : 4005)
#include "winternl.h"
#include <ntstatus.h>

using namespace lldb;
using namespace lldb_private;
using namespace llvm;

namespace lldb_private {

NativeProcessWindows::NativeProcessWindows(ProcessLaunchInfo &launch_info,
                                           NativeDelegate &delegate,
                                           llvm::Error &E)
    : NativeProcessProtocol(
          LLDB_INVALID_PROCESS_ID,
          PseudoTerminal::invalid_fd, // NativeProcessWindows owns the ConPTY.
          delegate),
      ProcessDebugger(), m_arch(launch_info.GetArchitecture()),
      m_stdio_communication("lldb.NativeProcessWindows.stdio") {
  ErrorAsOutParameter EOut(&E);
  DebugDelegateSP delegate_sp(new NativeDebugDelegate(*this));
  E = LaunchProcess(launch_info, delegate_sp).ToError();
  if (E)
    return;

  SetID(GetDebuggedProcessId());

  m_pty = launch_info.TakePTY();
  StartStdioForwarding();
}

NativeProcessWindows::NativeProcessWindows(lldb::pid_t pid, int terminal_fd,
                                           NativeDelegate &delegate,
                                           llvm::Error &E)
    : NativeProcessProtocol(pid, terminal_fd, delegate), ProcessDebugger(),
      m_stdio_communication("lldb.NativeProcessWindows.stdio") {
  ErrorAsOutParameter EOut(&E);
  DebugDelegateSP delegate_sp(new NativeDebugDelegate(*this));
  ProcessAttachInfo attach_info;
  attach_info.SetProcessID(pid);
  E = AttachProcess(pid, attach_info, delegate_sp).ToError();
  if (E)
    return;

  m_expecting_loader_int3 = true;

  SetID(GetDebuggedProcessId());

  ProcessInstanceInfo info;
  if (!Host::GetProcessInfo(pid, info)) {
    E = createStringError(inconvertibleErrorCode(),
                          "Cannot get process information");
    return;
  }
  m_arch = info.GetArchitecture();
}

Status NativeProcessWindows::Resume(const ResumeActionList &resume_actions) {
  Log *log = GetLog(WindowsLog::Process);
  Status error;
  llvm::sys::ScopedLock lock(m_mutex);

  StateType state = GetState();
  if (state == eStateStopped || state == eStateCrashed) {
    LLDB_LOG(log, "process {0} is in state {1}.  Resuming...",
             GetDebuggedProcessId(), state);
    std::lock_guard<std::recursive_mutex> guard(m_threads_mutex);
    LLDB_LOG(log, "resuming {0} threads.", m_threads.size());

    m_pending_library_events = false;

    bool failed = false;
    for (uint32_t i = 0; i < m_threads.size(); ++i) {
      auto thread = static_cast<NativeThreadWindows *>(m_threads[i].get());
      const ResumeAction *const action =
          resume_actions.GetActionForThread(thread->GetID(), true);
      if (action == nullptr)
        continue;

      switch (action->state) {
      case eStateRunning:
      case eStateStepping: {
        Status result = thread->DoResume(action->state);
        if (result.Fail()) {
          failed = true;
          LLDB_LOG(log,
                   "Trying to resume thread at index {0}, but failed with "
                   "error {1}.",
                   i, result);
        }
        break;
      }
      case eStateSuspended:
      case eStateStopped:
        break;

      default:
        return Status::FromErrorStringWithFormat(
            "NativeProcessWindows::%s (): unexpected state %s specified "
            "for pid %" PRIu64 ", tid %" PRIu64,
            __FUNCTION__, StateAsCString(action->state), GetID(),
            thread->GetID());
      }
    }

    if (failed) {
      error = Status::FromErrorString("NativeProcessWindows::DoResume failed");
    } else {
      SetState(eStateRunning);
    }

    // Resume the debug loop.
    ExceptionRecordSP active_exception =
        m_session_data->m_debugger->GetActiveException();
    if (active_exception) {
      // Resume the process and continue processing debug events.  Mask the
      // exception so that from the process's view, there is no indication that
      // anything happened.
      m_session_data->m_debugger->ContinueAsyncException(
          ExceptionResult::MaskException);
    } else {
      m_session_data->m_debugger->ContinueAsyncDllEvent();
    }
  } else {
    LLDB_LOG(log, "error: process {0} is in state {1}.  Returning...",
             GetDebuggedProcessId(), GetState());
  }

  return error;
}

NativeThreadWindows *
NativeProcessWindows::GetThreadByID(lldb::tid_t thread_id) {
  return static_cast<NativeThreadWindows *>(
      NativeProcessProtocol::GetThreadByID(thread_id));
}

Status NativeProcessWindows::Halt() {
  bool caused_stop = false;
  StateType state = GetState();
  if (state != eStateStopped) {
    m_pending_halt = true;
    Status err = HaltProcess(caused_stop);
    if (err.Fail() || !caused_stop)
      m_pending_halt = false;
    return err;
  }
  return Status();
}

Status NativeProcessWindows::Detach() {
  Status error;
  Log *log = GetLog(WindowsLog::Process);
  StateType state = GetState();
  if (state != eStateExited && state != eStateDetached) {
    error = DetachProcess();
    if (error.Success())
      SetState(eStateDetached);
    else
      LLDB_LOG(log, "Detaching process error: {0}", error);
  } else {
    error = Status::FromErrorStringWithFormatv(
        "error: process {0} in state = {1}, but "
        "cannot detach it in this state.",
        GetID(), state);
    LLDB_LOG(log, "error: {0}", error);
  }
  return error;
}

Status NativeProcessWindows::Signal(int signo) {
  Status error;
  error = Status::FromErrorString(
      "Windows does not support sending signals to processes");
  return error;
}

Status NativeProcessWindows::Interrupt() { return Halt(); }

Status NativeProcessWindows::Kill() {
  StateType state = GetState();
  return DestroyProcess(state);
}

Status NativeProcessWindows::IgnoreSignals(llvm::ArrayRef<int> signals) {
  return Status();
}

Status NativeProcessWindows::GetMemoryRegionInfo(lldb::addr_t load_addr,
                                                 MemoryRegionInfo &range_info) {
  return ProcessDebugger::GetMemoryRegionInfo(load_addr, range_info);
}

Status NativeProcessWindows::ReadMemory(const ProcessAddress &process_addr,
                                        void *buf, size_t size,
                                        size_t &bytes_read) {
  lldb::addr_t addr = process_addr.GetValue();
  return ProcessDebugger::ReadMemory(addr, buf, size, bytes_read);
}

Status NativeProcessWindows::DoWriteMemory(lldb::addr_t addr, const void *buf,
                                           size_t size, size_t &bytes_written) {
  return ProcessDebugger::WriteMemory(addr, buf, size, bytes_written);
}

llvm::Expected<lldb::addr_t>
NativeProcessWindows::AllocateMemory(size_t size, uint32_t permissions) {
  lldb::addr_t addr;
  Status ST = ProcessDebugger::AllocateMemory(size, permissions, addr);
  if (ST.Success())
    return addr;
  return ST.ToError();
}

llvm::Error NativeProcessWindows::DeallocateMemory(lldb::addr_t addr) {
  return ProcessDebugger::DeallocateMemory(addr).ToError();
}

lldb::addr_t NativeProcessWindows::GetSharedLibraryInfoAddress() { return 0; }

bool NativeProcessWindows::IsAlive() const {
  StateType state = GetState();
  switch (state) {
  case eStateCrashed:
  case eStateDetached:
  case eStateExited:
  case eStateInvalid:
  case eStateUnloaded:
    return false;
  default:
    return true;
  }
}

void NativeProcessWindows::SetStopReasonForThread(NativeThreadWindows &thread,
                                                  lldb::StopReason reason,
                                                  std::string description) {
  SetCurrentThreadID(thread.GetID());

  ThreadStopInfo stop_info;
  stop_info.reason = reason;
  // No signal support on Windows but required to provide a 'valid' signum.
  stop_info.signo = SIGTRAP;

  if (reason == StopReason::eStopReasonException) {
    stop_info.details.exception.type = 0;
    stop_info.details.exception.data_count = 0;
  }

  thread.SetStopReason(stop_info, description);
}

void NativeProcessWindows::StopThread(lldb::tid_t thread_id,
                                      lldb::StopReason reason,
                                      std::string description) {
  NativeThreadWindows *thread = GetThreadByID(thread_id);
  if (!thread)
    return;

  Log *log = GetLog(WindowsLog::Thread);
  std::lock_guard<std::recursive_mutex> guard(m_threads_mutex);
  for (uint32_t i = 0; i < m_threads.size(); ++i) {
    auto t = static_cast<NativeThreadWindows *>(m_threads[i].get());
    if (Status error = t->DoStop(); error.Fail())
      LLDB_LOG(log, "failed to stop thread {0}: {1}", t->GetID(), error);
  }
  SetStopReasonForThread(*thread, reason, description);
}

size_t NativeProcessWindows::UpdateThreads() {
  std::lock_guard<std::recursive_mutex> guard(m_threads_mutex);
  return m_threads.size();
}

llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>>
NativeProcessWindows::GetAuxvData() const {
  // Not available on this target.
  return llvm::errc::not_supported;
}

llvm::Expected<llvm::ArrayRef<uint8_t>>
NativeProcessWindows::GetSoftwareBreakpointTrapOpcode(size_t size_hint) {
  static const uint8_t g_aarch64_opcode[] = {0x00, 0x00, 0x3e,
                                             0xd4};     // brk #0xf000
  static const uint8_t g_thumb_opcode[] = {0xfe, 0xde}; // udf #0xfe

  switch (GetArchitecture().GetMachine()) {
  case llvm::Triple::aarch64:
    return llvm::ArrayRef(g_aarch64_opcode);

  case llvm::Triple::arm:
  case llvm::Triple::thumb:
    return llvm::ArrayRef(g_thumb_opcode);

  default:
    return NativeProcessProtocol::GetSoftwareBreakpointTrapOpcode(size_hint);
  }
}

size_t NativeProcessWindows::GetSoftwareBreakpointPCOffset() {
  // Windows always reports an incremented PC after a breakpoint is hit,
  // even on ARM.
  return cantFail(GetSoftwareBreakpointTrapOpcode(0)).size();
}

bool NativeProcessWindows::FindSoftwareBreakpoint(lldb::addr_t addr) {
  return m_software_breakpoints.find(addr) != m_software_breakpoints.end();
}

Status NativeProcessWindows::SetBreakpoint(lldb::addr_t addr, uint32_t size,
                                           bool hardware) {
  if (hardware)
    return SetHardwareBreakpoint(addr, size);
  return SetSoftwareBreakpoint(addr, size);
}

Status NativeProcessWindows::RemoveBreakpoint(lldb::addr_t addr,
                                              bool hardware) {
  if (hardware)
    return RemoveHardwareBreakpoint(addr);
  return RemoveSoftwareBreakpoint(addr);
}

// Get the path of a module loaded in the target process, as the loader recorded
// it.
//
// Keep the loader's spelling.
static bool GetLoadedModulePath(HANDLE process, HMODULE module,
                                std::string &path) {
  std::vector<wchar_t> name(MAX_PATH);
  DWORD len = 0;
  while (true) {
    len = ::GetModuleFileNameExW(process, module, name.data(),
                                 static_cast<DWORD>(name.size()));
    if (len == 0)
      return false;
    if (len < name.size())
      break;
    if (name.size() >= PATHCCH_MAX_CCH)
      return false;
    name.resize(name.size() * 2);
  }

  std::wstring wpath(name.data(), len);
  if (!llvm::convertWideToUTF8(wpath, path))
    return false;
  path = StripExtendedLengthPrefix(path);

  // The loader's path often differs from the on-disk one only in case (e.g.
  // C:\windows\System32\KERNEL32.DLL). Open the image file to get its on-disk
  // spelling, and use it if that's the only difference.
  AutoHandle file(::CreateFileW(
      wpath.c_str(), 0, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
      nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr));

  if (!file.IsValid())
    return true;

  // Unlike GetModuleFileNameExW, GetFinalPathNameByHandleW reports the buffer
  // size it needs instead of truncating, so start empty and let the first call
  // size the buffer rather than guessing.
  std::vector<wchar_t> full;
  while (true) {
    DWORD needed = ::GetFinalPathNameByHandleW(
        file.get(), full.data(), static_cast<DWORD>(full.size()),
        FILE_NAME_NORMALIZED | VOLUME_NAME_DOS);
    if (needed == 0)
      break;
    if (needed < full.size()) {
      std::string canonical;
      if (!llvm::convertWideToUTF8(std::wstring_view(full.data(), needed),
                                   canonical))
        break;
      // GetFinalPathNameByHandleW returns an extended-length ("\\?\") path.
      canonical = StripExtendedLengthPrefix(canonical);
      if (llvm::StringRef(canonical).equals_insensitive(path))
        path = std::move(canonical);
      break;
    }
    full.resize(needed);
  }

  return true;
}

Status NativeProcessWindows::CacheLoadedModules() {
  Status error;
  if (!m_loaded_modules.IsEmpty())
    return Status();

  AutoHandle process(::OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ,
                                   FALSE, GetID()),
                     nullptr);
  if (!process.IsValid())
    return Status(::GetLastError(), eErrorTypeWin32);

  AutoHandle snapshot(::CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, GetID()));
  if (!snapshot.IsValid())
    return Status(::GetLastError(), eErrorTypeWin32);

  MODULEENTRY32W me;
  me.dwSize = sizeof(MODULEENTRY32W);
  if (::Module32FirstW(snapshot.get(), &me)) {
    do {
      std::string path;
      if (!GetLoadedModulePath(process.get(), me.hModule, path))
        continue;

      FileSpec file_spec(path);
      FileSystem::Instance().Resolve(file_spec);
      m_loaded_modules.Add(file_spec, reinterpret_cast<addr_t>(me.modBaseAddr));
    } while (::Module32NextW(snapshot.get(), &me));
  }

  if (!m_loaded_modules.IsEmpty())
    return Status();

  error = Status(::GetLastError(), lldb::ErrorType::eErrorTypeWin32);
  return error;
}

Status NativeProcessWindows::GetLoadedModuleFileSpec(const char *module_path,
                                                     FileSpec &file_spec) {
  Status error = CacheLoadedModules();
  if (error.Fail())
    return error;

  FileSpec module_file_spec(module_path);
  FileSystem::Instance().Resolve(module_file_spec);
  if (const FileSpec *found = m_loaded_modules.FindFile(module_file_spec)) {
    file_spec = *found;
    return Status();
  }
  return Status::FromErrorStringWithFormat(
      "Module (%s) not found in process %" PRIu64 "!",
      module_file_spec.GetPath().c_str(), GetID());
}

Status
NativeProcessWindows::GetFileLoadAddress(const llvm::StringRef &file_name,
                                         lldb::addr_t &load_addr) {
  Status error = CacheLoadedModules();
  if (error.Fail())
    return error;

  load_addr = LLDB_INVALID_ADDRESS;
  FileSpec file_spec(file_name);
  FileSystem::Instance().Resolve(file_spec);
  if (std::optional<addr_t> base = m_loaded_modules.GetBaseAddress(file_spec)) {
    load_addr = *base;
    return Status();
  }
  return Status::FromErrorStringWithFormat(
      "Can't get loaded address of file (%s) in process %" PRIu64 "!",
      file_spec.GetPath().c_str(), GetID());
}

llvm::Expected<std::vector<LoadedLibraryInfo>>
NativeProcessWindows::GetLoadedLibraries() {
  if (Status error = CacheLoadedModules(); error.Fail())
    return error.ToError();

  std::vector<LoadedLibraryInfo> libs;
  libs.reserve(m_loaded_modules.GetSize());
  for (const auto &[file_spec, base_addrs] : m_loaded_modules) {
    LoadedLibraryInfo info;
    info.name = file_spec.GetPath();
    info.base_addr = base_addrs.front();
    libs.push_back(std::move(info));
  }
  return libs;
}

bool NativeProcessWindows::HasPendingLibraryEvents() {
  return m_pending_library_events;
}

void NativeProcessWindows::OnExitProcess(uint32_t exit_code) {
  Log *log = GetLog(WindowsLog::Process);
  LLDB_LOG(log, "Process {0} exited with code {1}", GetID(), exit_code);

  // Closing the ConPTY signals EOF on the parent-side STDOUT pipe so the
  // read thread can exit. Tear it down before the debuggee is destroyed.
  StopStdioForwarding();

  ProcessDebugger::OnExitProcess(exit_code);

  // No signal involved.  It is just an exit event.
  WaitStatus wait_status(WaitStatus::Exit, exit_code);
  SetExitStatus(wait_status, true);

  // Notify the native delegate.
  SetState(eStateExited, true);
}

void NativeProcessWindows::OnDebuggerConnected(lldb::addr_t image_base) {
  Log *log = GetLog(WindowsLog::Process);
  LLDB_LOG(log, "Debugger connected to process {0}. Image base = {1:x}",
           GetDebuggedProcessId(), image_base);

  // This is the earliest chance we can resolve the process ID and
  // architecture if we don't know them yet.
  if (GetID() == LLDB_INVALID_PROCESS_ID)
    SetID(GetDebuggedProcessId());

  ProcessInstanceInfo info;
  bool got_info = Host::GetProcessInfo(GetDebuggedProcessId(), info);

  if (GetArchitecture().GetMachine() == llvm::Triple::UnknownArch) {
    if (!got_info) {
      LLDB_LOG(log, "Cannot get process information during debugger connecting "
                    "to process");
      return;
    }
    SetArchitecture(info.GetArchitecture());
  }

  if (got_info) {
    FileSpec exe = info.GetExecutableFile();
    if (const std::string &image_path =
            m_session_data->m_debugger->GetImagePath();
        !image_path.empty() &&
        !llvm::StringRef(image_path).equals_insensitive(exe.GetPath()))
      exe = FileSpec(image_path);
    if (exe) {
      FileSystem::Instance().Resolve(exe);
      m_loaded_modules.Add(exe, image_base);
    }
  }

  // The very first one shall always be the main thread.
  std::lock_guard<std::recursive_mutex> guard(m_threads_mutex);
  assert(m_threads.empty());
  m_threads.push_back(std::make_unique<NativeThreadWindows>(
      *this, m_session_data->m_debugger->GetMainThread()));
}

ExceptionResult
NativeProcessWindows::HandleSingleStepException(const ExceptionRecord &record) {
  uint32_t wp_id = LLDB_INVALID_INDEX32;
#ifndef __aarch64__
  Log *log = GetLog(WindowsLog::Exception);
  if (NativeThreadWindows *thread = GetThreadByID(record.GetThreadID())) {
    NativeRegisterContextWindows &reg_ctx = thread->GetRegisterContext();
    Status error =
        reg_ctx.GetWatchpointHitIndex(wp_id, record.GetExceptionAddress());
    if (error.Fail())
      LLDB_LOG(log,
               "received error while checking for watchpoint hits, pid = "
               "{0}, error = {1}",
               thread->GetID(), error);
    if (wp_id != LLDB_INVALID_INDEX32) {
      addr_t wp_addr = reg_ctx.GetWatchpointAddress(wp_id);
      addr_t wp_hit_addr = reg_ctx.GetWatchpointHitAddress(wp_id);
      std::string desc =
          formatv("{0} {1} {2}", wp_addr, wp_id, wp_hit_addr).str();
      StopThread(record.GetThreadID(), StopReason::eStopReasonWatchpoint, desc);
    }
  }
#endif
  if (wp_id == LLDB_INVALID_INDEX32)
    StopThread(record.GetThreadID(), StopReason::eStopReasonTrace);

  SetState(eStateStopped, true);
  return ExceptionResult::MaskException;
}

ExceptionResult
NativeProcessWindows::HandleBreakpointException(const ExceptionRecord &record) {
  Log *log = GetLog(WindowsLog::Exception);
  const auto exception_addr = record.GetExceptionAddress();
  const auto thread_id = record.GetThreadID();

  if (NativeThreadWindows *stop_thread = GetThreadByID(thread_id)) {
    auto &reg_ctx = stop_thread->GetRegisterContext();

    if (FindSoftwareBreakpoint(exception_addr)) {
      LLDB_LOG(log, "Hit non-loader breakpoint at address {0:x}.",
               exception_addr);
      StopThread(thread_id, StopReason::eStopReasonBreakpoint);
      // The current PC is AFTER the BP opcode, on all architectures.
      reg_ctx.SetPC(reg_ctx.GetPC() - GetSoftwareBreakpointPCOffset());
      SetState(eStateStopped, true);
      return ExceptionResult::MaskException;
    }

    // This block of code will only be entered in case of a hardware
    // watchpoint or breakpoint hit on AArch64. However, we only handle
    // hardware watchpoints below as breakpoints are not yet supported.
    const ArrayRef<uint64_t> args = record.GetExceptionArguments();
    // Check that the ExceptionInformation array of EXCEPTION_RECORD
    // contains at least two elements: the first is a read-write flag
    // indicating the type of data access operation (read or write) while
    // the second contains the virtual address of the accessed data.
    if (args.size() >= 2) {
      uint32_t hw_id = LLDB_INVALID_INDEX32;
      Status error = reg_ctx.GetWatchpointHitIndex(hw_id, args[1]);
      if (error.Fail())
        LLDB_LOG(log,
                 "received error while checking for watchpoint hits, pid = "
                 "{0}, error = {1}",
                 thread_id, error);

      if (hw_id != LLDB_INVALID_INDEX32) {
        std::string desc =
            formatv("{0} {1} {2}", reg_ctx.GetWatchpointAddress(hw_id), hw_id,
                    exception_addr)
                .str();
        StopThread(thread_id, StopReason::eStopReasonWatchpoint, desc);
        SetState(eStateStopped, true);
        return ExceptionResult::MaskException;
      }
    }
  }

  if (!m_initial_stop_seen) {
    m_initial_stop_seen = true;
    LLDB_LOG(log,
             "Hit loader breakpoint at address {0:x}, setting initial stop "
             "event.",
             exception_addr);

    // We are required to report the reason for the first stop after
    // launching or being attached.
    if (NativeThreadWindows *thread = GetThreadByID(thread_id))
      SetStopReasonForThread(*thread, StopReason::eStopReasonBreakpoint);

    // Do not notify the native delegate (e.g. llgs) since at this moment
    // the program hasn't returned from Manager::Launch() and the delegate
    // might not have an valid native process to operate on.
    SetState(eStateStopped, false);

    // Hit the initial stop. Continue the application.
    return ExceptionResult::BreakInDebugger;
  }

  // Our own DebugBreakProcess() injection, used to implement
  // Halt()/Interrupt().
  if (m_pending_halt) {
    LLDB_LOG(log,
             "DebugBreakProcess injection treated as Halt SIGSTOP for tid "
             "{0:x}",
             thread_id);
    m_pending_halt = false;
    ThreadStopInfo signal_info;
    signal_info.reason = StopReason::eStopReasonSignal;
    signal_info.signo = 19; // SIGSTOP on POSIX

    // Halt all threads at the kernel level.
    {
      std::lock_guard<std::recursive_mutex> guard(m_threads_mutex);
      for (uint32_t i = 0; i < m_threads.size(); ++i) {
        auto t = static_cast<NativeThreadWindows *>(m_threads[i].get());
        if (Status err = t->DoStop(); err.Fail()) {
          LLDB_LOG(log, "Failed to stop thread {1:x}: {0}", t->GetID(),
                   err.GetError());
          exit(1);
        }
      }
    }
    SetCurrentThreadID(thread_id);
    if (NativeThreadWindows *injected = GetThreadByID(thread_id))
      injected->SetStopReason(signal_info, "interrupt");
    SetState(eStateStopped, true);
    return ExceptionResult::BreakInDebugger;
  }

  if (m_expecting_loader_int3 && IsSystemModuleAddress(exception_addr)) {
    m_expecting_loader_int3 = false;
    LLDB_LOG(log,
             "Skipping expected loader breakpoint at address {0:x} in a "
             "system module.",
             exception_addr);
    return ExceptionResult::MaskException;
  }

  std::string desc = formatv("Exception {0:x8} encountered at address {1:x8}",
                             record.GetExceptionValue(), exception_addr)
                         .str();
  StopThread(thread_id, StopReason::eStopReasonException, std::move(desc));
  SetState(eStateStopped, true);
  return ExceptionResult::MaskException;
}

ExceptionResult
NativeProcessWindows::HandleGenericException(bool first_chance,
                                             const ExceptionRecord &record) {
  Log *log = GetLog(WindowsLog::Exception);
  LLDB_LOG(log,
           "Debugger thread reported exception {0:x} at address {1:x} "
           "(first_chance={2})",
           record.GetExceptionValue(), record.GetExceptionAddress(),
           first_chance);

  if (first_chance)
    return ExceptionResult::SendToApplication;

  std::string desc;
  llvm::raw_string_ostream desc_stream(desc);
  desc_stream << "Exception " << llvm::format_hex(record.GetExceptionValue(), 8)
              << " encountered at address "
              << llvm::format_hex(record.GetExceptionAddress(), 8);
  record.Dump(desc_stream);
  StopThread(record.GetThreadID(), StopReason::eStopReasonException,
             std::move(desc));

  SetState(eStateStopped, true);
  return ExceptionResult::BreakInDebugger;
}

ExceptionResult
NativeProcessWindows::OnDebugException(bool first_chance,
                                       const ExceptionRecord &record) {
  llvm::sys::ScopedLock lock(m_mutex);

  // Handle the exception first to keep track of the stop reason.
  ExceptionResult result;
  switch (record.GetExceptionValue()) {
  case DWORD(STATUS_SINGLE_STEP):
  case STATUS_WX86_SINGLE_STEP:
    result = HandleSingleStepException(record);
    break;
  case DWORD(STATUS_BREAKPOINT):
  case STATUS_WX86_BREAKPOINT:
    result = HandleBreakpointException(record);
    break;
  default:
    result = HandleGenericException(first_chance, record);
    break;
  }

  // Let the debugger establish the internal status.
  ProcessDebugger::OnDebugException(first_chance, record);

  return result;
}

void NativeProcessWindows::OnCreateThread(const HostThread &new_thread) {
  llvm::sys::ScopedLock lock(m_mutex);

  auto thread = std::make_unique<NativeThreadWindows>(*this, new_thread);
  thread->GetRegisterContext().ClearAllHardwareWatchpoints();
  for (const auto &pair : GetWatchpointMap()) {
    const NativeWatchpoint &wp = pair.second;
    thread->SetWatchpoint(wp.m_addr, wp.m_size, wp.m_watch_flags,
                          wp.m_hardware);
  }

  if (StateType state = GetState();
      state == eStateStopped || state == eStateCrashed) {
    if (Status error = thread->DoStop(); error.Fail()) {
      Log *log = GetLog(WindowsLog::Thread);
      LLDB_LOG(log, "failed to suspend newly-created thread {0}: {1}",
               thread->GetID(), error);
    }
    ThreadStopInfo stop_info;
    stop_info.reason = lldb::eStopReasonNone;
    thread->SetStopReason(stop_info, "");
  }

  std::lock_guard<std::recursive_mutex> guard(m_threads_mutex);
  m_threads.push_back(std::move(thread));
}

void NativeProcessWindows::OnExitThread(lldb::tid_t thread_id,
                                        uint32_t exit_code) {
  std::lock_guard<std::recursive_mutex> guard(m_threads_mutex);
  llvm::erase_if(m_threads, [thread_id](const auto &t) {
    return t->GetID() == thread_id;
  });
}

DllEventAction NativeProcessWindows::OnLoadDll(const ModuleSpec &module_spec,
                                               lldb::addr_t module_addr,
                                               lldb::tid_t thread_id) {
  Log *log = GetLog(WindowsLog::Process);
  llvm::sys::ScopedLock lock(m_mutex);

  FileSpec resolved = module_spec.GetFileSpec();
  if (resolved) {
    FileSystem::Instance().Resolve(resolved);
    m_loaded_modules.Add(resolved, module_addr);
  }
  m_pending_library_events = true;

  if (!m_initial_stop_seen || !m_client_supports_libraries_read)
    return DllEventAction::ContinueDebugLoop;

  // Can't resolve a breakpoint in a system DLL.
  if (!resolved || ProcessDebugger::IsSystemDLL(resolved.GetPath()))
    return DllEventAction::ContinueDebugLoop;

  {
    std::lock_guard<std::recursive_mutex> guard(m_threads_mutex);
    NativeThreadWindows *loader_thread = GetThreadByID(thread_id);
    if (!loader_thread && !m_threads.empty()) {
      LLDB_LOG(log,
               "LOAD_DLL on unknown tid {0:x}. Falling back to main thread.",
               thread_id);
      loader_thread = static_cast<NativeThreadWindows *>(m_threads[0].get());
    }
    if (loader_thread) {
      SetCurrentThreadID(loader_thread->GetID());
      if (loader_thread->DoStop().Fail())
        LLDB_LOG(log, "Failed to suspend thread {0} on LOAD_DLL.",
                 loader_thread->GetID());
      ThreadStopInfo info;
      info.reason = lldb::eStopReasonNone;
      info.signo = 0;
      loader_thread->SetStopReason(info, "");
    }
  }
  SetState(eStateStopped, true);

  return DllEventAction::ParkDebugLoop;
}

DllEventAction NativeProcessWindows::OnUnloadDll(lldb::addr_t module_addr,
                                                 lldb::tid_t thread_id) {
  Log *log = GetLog(WindowsLog::Process);
  llvm::sys::ScopedLock lock(m_mutex);

  FileSpec unloaded_spec = m_loaded_modules.Remove(module_addr);
  m_pending_library_events = true;

  if (!m_initial_stop_seen || !m_client_supports_libraries_read)
    return DllEventAction::ContinueDebugLoop;

  if (!unloaded_spec || ProcessDebugger::IsSystemDLL(unloaded_spec.GetPath()))
    return DllEventAction::ContinueDebugLoop;

  {
    std::lock_guard<std::recursive_mutex> guard(m_threads_mutex);
    NativeThreadWindows *unloader_thread = GetThreadByID(thread_id);
    if (!unloader_thread && !m_threads.empty()) {
      LLDB_LOG(log,
               "UNLOAD_DLL on unknown tid {0:x}. Falling back to main thread.",
               thread_id);
      unloader_thread = static_cast<NativeThreadWindows *>(m_threads[0].get());
    }
    if (unloader_thread) {
      SetCurrentThreadID(unloader_thread->GetID());
      if (unloader_thread->DoStop().Fail())
        LLDB_LOG(log, "Failed to suspend thread {0} on UNLOAD_DLL.",
                 unloader_thread->GetID());
      ThreadStopInfo info;
      info.reason = lldb::eStopReasonNone;
      info.signo = 0;
      unloader_thread->SetStopReason(info, "");
    }
  }
  SetState(eStateStopped, true);
  return DllEventAction::ParkDebugLoop;
}

void NativeProcessWindows::OnDebugString(lldb::addr_t debug_string_addr,
                                         bool is_unicode,
                                         uint16_t length_lower_word) {
  Log *log = GetLog(WindowsLog::Process);

  llvm::SmallVector<char, 256> buffer;
  if (llvm::Error err = ProcessDebugger::ReadDebugString(
          debug_string_addr, is_unicode, length_lower_word, buffer)) {
    std::string err_str = llvm::toString(std::move(err));
    std::string msg =
        llvm::formatv("Failed to read debug string at {0:x} "
                      "(size & 0xffff={1}, unicode={2}): {3}\n",
                      debug_string_addr, length_lower_word, is_unicode, err_str)
            .str();
    LLDB_LOG(log, "{0}", msg);
    m_delegate.NewProcessOutput(this, llvm::StringRef(msg));
    return;
  }
  if (buffer.empty())
    return;

  if (is_unicode) {
    assert(buffer.size() % 2 == 0);
    llvm::ArrayRef<unsigned short> utf16(
        reinterpret_cast<const unsigned short *>(buffer.data()),
        buffer.size() / 2);
    std::string out;
    if (!llvm::convertUTF16ToUTF8String(utf16, out)) {
      LLDB_LOG(log, "Debug string is not valid Utf 16");
      return;
    }
    m_delegate.NewProcessOutput(this, llvm::StringRef(out.data(), out.size()));
  } else {
    m_delegate.NewProcessOutput(this,
                                llvm::StringRef(buffer.data(), buffer.size()));
  }
}

llvm::Expected<std::unique_ptr<NativeProcessProtocol>>
NativeProcessWindows::Manager::Launch(
    ProcessLaunchInfo &launch_info,
    NativeProcessProtocol::NativeDelegate &native_delegate) {
  Error E = Error::success();
  auto process_up = std::unique_ptr<NativeProcessWindows>(
      new NativeProcessWindows(launch_info, native_delegate, E));
  if (E)
    return std::move(E);
  return std::move(process_up);
}

llvm::Expected<std::unique_ptr<NativeProcessProtocol>>
NativeProcessWindows::Manager::Attach(
    lldb::pid_t pid, NativeProcessProtocol::NativeDelegate &native_delegate) {
  Error E = Error::success();
  // Set pty primary fd invalid since it is not available.
  auto process_up = std::unique_ptr<NativeProcessWindows>(
      new NativeProcessWindows(pid, -1, native_delegate, E));
  if (E)
    return std::move(E);
  return std::move(process_up);
}

NativeProcessWindows::~NativeProcessWindows() { StopStdioForwarding(); }

void NativeProcessWindows::StartStdioForwarding() {
  if (!m_pty || !m_pty->IsConnected())
    return;

  m_stdio_communication.SetConnection(
      std::make_unique<ConnectionConPTY>(m_pty));
  if (!m_stdio_communication.IsConnected())
    return;
  m_stdio_communication.SetReadThreadBytesReceivedCallback(
      &NativeProcessWindows::STDIOReadThreadBytesReceived, this);
  m_stdio_communication.StartReadThread();
}

void NativeProcessWindows::StopStdioForwarding() {
  if (!m_stdio_communication.HasConnection())
    return;

  if (m_pty)
    m_pty->Close();

  if (m_stdio_communication.ReadThreadIsRunning())
    m_stdio_communication.JoinReadThread();

  if (m_stdio_communication.HasConnection())
    m_stdio_communication.Disconnect();
}

void NativeProcessWindows::STDIOReadThreadBytesReceived(void *baton,
                                                        const void *src,
                                                        size_t src_len) {
  auto *self = static_cast<NativeProcessWindows *>(baton);
  if (src_len == 0)
    return;
  self->m_delegate.NewProcessOutput(
      self, llvm::StringRef(static_cast<const char *>(src), src_len));
}

size_t NativeProcessWindows::WriteStdin(const void *buf, size_t len,
                                        Status &error) {
  if (!m_stdio_communication.HasConnection()) {
    error = Status::FromErrorString(
        "no ConPTY connection on this NativeProcessWindows");
    return 0;
  }
  ConnectionStatus status;
  size_t written = m_stdio_communication.Write(buf, len, status, &error);
  if (status != eConnectionStatusSuccess && error.Success())
    error = Status::FromErrorStringWithFormatv(
        "ConPTY stdin write returned status {0}", static_cast<int>(status));
  return written;
}
} // namespace lldb_private
