//===-- 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/Target/UnixSignals.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());
      thread->ClearSingleStepping();
      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();

  bool started = m_session_data && m_session_data->m_initial_stop_received;
  ProcessDebugger::OnExitProcess(exit_code);

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

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

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()));
}

bool NativeProcessWindows::RewindTrapOfRemovedBreakpoint(
    const ExceptionRecord &record) {
  if (!m_initial_stop_seen)
    return false;
  NativeThreadWindows *thread = GetThreadByID(record.GetThreadID());
  if (!thread)
    return false;
  const lldb::addr_t trap_addr = record.GetExceptionAddress();
  llvm::ArrayRef<uint8_t> trap_opcode =
      cantFail(GetSoftwareBreakpointTrapOpcode(0));
  NativeRegisterContextWindows &reg_ctx = thread->GetRegisterContext();
  if (reg_ctx.GetPC() != trap_addr + trap_opcode.size())
    return false;
  llvm::SmallVector<uint8_t, 4> bytes(trap_opcode.size(), 0);
  size_t bytes_read = 0;
  if (ProcessDebugger::ReadMemory(trap_addr, bytes.data(), bytes.size(),
                                  bytes_read)
          .Fail() ||
      bytes_read != bytes.size() ||
      llvm::ArrayRef<uint8_t>(bytes) == trap_opcode)
    return false;
  LLDB_LOG(GetLog(WindowsLog::Exception),
           "Trap at {0:x} on thread {1:x} is from a removed breakpoint, "
           "rewinding the thread onto the original instruction.",
           trap_addr, thread->GetID());
  return reg_ctx.SetPC(trap_addr).Success();
}

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) {
    NativeThreadWindows *thread = GetThreadByID(record.GetThreadID());
    if (thread && !thread->IsSingleStepping()) {
      LLDB_LOG(GetLog(WindowsLog::Exception),
               "ignoring a late single-step trap on thread {0:x}, which this "
               "resume did not step",
               record.GetThreadID());
      return ExceptionResult::MaskException;
    }
    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 (RewindTrapOfRemovedBreakpoint(record))
      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 =
        UnixSignals::CreateForHost()->GetSignalNumberFromName("SIGSTOP");

    // 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);
  const StateType state = GetState();
  std::lock_guard<std::recursive_mutex> threads_guard(m_threads_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 (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, "");
  }

  m_threads.push_back(std::move(thread));
}

void NativeProcessWindows::OnExitThread(lldb::tid_t thread_id,
                                        uint32_t exit_code) {
  llvm::sys::ScopedLock lock(m_mutex);
  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() {
  EndDebugSession();
  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;

  m_stdio_communication.SynchronizeWithReadThread();

  if (m_pty)
    m_pty->Close();

  // Close() cancels the read pending on the pipe, but one that the read thread
  // is about to start would only return at its 5s timeout: EOF cannot come
  // while the inferior is held at its exit debug event. Wake the thread so that
  // it sees the closed PTY right away.
  m_stdio_communication.InterruptRead();

  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
