//===-- DebuggerThread.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 "DebuggerThread.h"
#include "ExceptionRecord.h"
#include "IDebugDelegate.h"

#include "lldb/Core/ModuleSpec.h"
#include "lldb/Host/ProcessLaunchInfo.h"
#include "lldb/Host/ThreadLauncher.h"
#include "lldb/Host/windows/AutoHandle.h"
#include "lldb/Host/windows/HostProcessWindows.h"
#include "lldb/Host/windows/HostThreadWindows.h"
#include "lldb/Host/windows/LazyImport.h"
#include "lldb/Host/windows/PathUtils.h"
#include "lldb/Host/windows/ProcessLauncherWindows.h"
#include "lldb/Target/Process.h"
#include "lldb/Utility/FileSpec.h"
#include "lldb/Utility/Log.h"
#include "lldb/Utility/Predicate.h"
#include "lldb/Utility/Status.h"

#include "Plugins/Process/Windows/Common/ProcessWindowsLog.h"

#include "lldb/Utility/LLDBLog.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/Support/ConvertUTF.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/Threading.h"
#include "llvm/Support/raw_ostream.h"

#include <optional>
#include <pathcch.h>
#include <psapi.h>
#include <winternl.h>

#ifndef STATUS_WX86_BREAKPOINT
#define STATUS_WX86_BREAKPOINT 0x4000001FL // For WOW64
#endif

using namespace lldb;
using namespace lldb_private;

typedef BOOL WINAPI WaitForDebugEventFn(LPDEBUG_EVENT, DWORD);
static WaitForDebugEventFn *g_wait_for_debug_event = nullptr;

/// WaitForDebugEventEx is only available on Windows 10+. This lazily checks if
/// the function is available and falls back to WaitForDebugEvent if
/// unavailable. The -Ex version ensures correct forwarding of
/// OutputDebugStringW events.
static void InitializeWaitForDebugEvent() {
  static LazyImport<WaitForDebugEventFn *> s_wait_for_debug_event_ex = {
      L"kernel32.dll", "WaitForDebugEventEx"};

  if (g_wait_for_debug_event)
    return;

  if (!s_wait_for_debug_event_ex) {
    LLDB_LOG(
        GetLog(LLDBLog::Host),
        "WaitForDebugEventEx unavailable, using WaitForDebugEvent instead. "
        "Unicode strings from OutputDebugStringW might show incorrectly.");
    g_wait_for_debug_event = &WaitForDebugEvent;
  } else {
    g_wait_for_debug_event = *s_wait_for_debug_event_ex;
  }
}

DebuggerThread::DebuggerThread(DebugDelegateSP debug_delegate)
    : m_debug_delegate(debug_delegate), m_pid_to_detach(0),
      m_is_shutting_down(false) {
  InitializeWaitForDebugEvent();
  m_debugging_ended_event = ::CreateEvent(nullptr, TRUE, FALSE, nullptr);
}

DebuggerThread::~DebuggerThread() { ::CloseHandle(m_debugging_ended_event); }

Status DebuggerThread::DebugLaunch(const ProcessLaunchInfo &launch_info) {
  Log *log = GetLog(WindowsLog::Process);
  LLDB_LOG(log, "launching '{0}'", launch_info.GetExecutableFile().GetPath());

  Status result;
  llvm::Expected<HostThread> secondary_thread = ThreadLauncher::LaunchThread(
      "lldb.plugin.process-windows.secondary[?]",
      [this, launch_info] { return DebuggerThreadLaunchRoutine(launch_info); });
  if (!secondary_thread) {
    result = Status::FromError(secondary_thread.takeError());
    LLDB_LOG(log, "couldn't launch debugger thread. {0}", result);
  }

  return result;
}

Status DebuggerThread::DebugAttach(lldb::pid_t pid,
                                   const ProcessAttachInfo &attach_info) {
  Log *log = GetLog(WindowsLog::Process);
  LLDB_LOG(log, "attaching to '{0}'", pid);

  Status result;
  llvm::Expected<HostThread> secondary_thread = ThreadLauncher::LaunchThread(
      "lldb.plugin.process-windows.secondary[?]", [this, pid, attach_info] {
        return DebuggerThreadAttachRoutine(pid, attach_info);
      });
  if (!secondary_thread) {
    result = Status::FromError(secondary_thread.takeError());
    LLDB_LOG(log, "couldn't attach to process '{0}'. {1}", pid, result);
  }

  return result;
}

lldb::thread_result_t DebuggerThread::DebuggerThreadLaunchRoutine(
    const ProcessLaunchInfo &launch_info) {
  // Grab a shared_ptr reference to this so that we know it won't get deleted
  // until after the thread routine has exited.
  std::shared_ptr<DebuggerThread> this_ref(shared_from_this());

  Log *log = GetLog(WindowsLog::Process);
  LLDB_LOG(log, "preparing to launch '{0}' on background thread.",
           launch_info.GetExecutableFile().GetPath());

  Status error;
  ProcessLauncherWindows launcher;
  HostProcess process(launcher.LaunchProcess(launch_info, error));
  // If we couldn't create the process, notify waiters immediately.  Otherwise
  // enter the debug loop and wait until we get the create process debug
  // notification.  Note that if the process was created successfully, we can
  // throw away the process handle we got from CreateProcess because Windows
  // will give us another (potentially more useful?) handle when it sends us
  // the CREATE_PROCESS_DEBUG_EVENT.
  if (error.Success())
    DebugLoop();
  else
    m_debug_delegate->OnDebuggerError(error, 0);

  return {};
}

lldb::thread_result_t DebuggerThread::DebuggerThreadAttachRoutine(
    lldb::pid_t pid, const ProcessAttachInfo &attach_info) {
  // Grab a shared_ptr reference to this so that we know it won't get deleted
  // until after the thread routine has exited.
  std::shared_ptr<DebuggerThread> this_ref(shared_from_this());

  Log *log = GetLog(WindowsLog::Process);
  LLDB_LOG(log, "preparing to attach to process '{0}' on background thread.",
           pid);

  if (!DebugActiveProcess(static_cast<DWORD>(pid))) {
    Status error(::GetLastError(), eErrorTypeWin32);
    m_debug_delegate->OnDebuggerError(error, 0);
    return {};
  }

  // The attach was successful, enter the debug loop.  From here on out, this
  // is no different than a create process operation, so all the same comments
  // in DebugLaunch should apply from this point out.
  DebugLoop();

  return {};
}

Status DebuggerThread::StopDebugging(bool terminate) {
  Status error;

  lldb::pid_t pid = m_process.GetProcessId();

  Log *log = GetLog(WindowsLog::Process);
  LLDB_LOG(log, "terminate = {0}, inferior={1}.", terminate, pid);

  // Set m_is_shutting_down to true if it was false.  Return if it was already
  // true.
  bool expected = false;
  if (!m_is_shutting_down.compare_exchange_strong(expected, true))
    return error;

  // Make a copy of the process, since the termination sequence will reset
  // DebuggerThread's internal copy and it needs to remain open for the Wait
  // operation.
  HostProcess process_copy = m_process;
  lldb::process_t handle = m_process.GetNativeProcess().GetSystemHandle();

  if (terminate) {
    if (handle != nullptr && handle != LLDB_INVALID_PROCESS) {
      // Initiate the termination before continuing the exception, so that the
      // next debug event we get is the exit process event, and not some other
      // event.
      BOOL terminate_succeeded = TerminateProcess(handle, 0);
      LLDB_LOG(log,
               "calling TerminateProcess({0}, 0) (inferior={1}), success={2}",
               handle, pid, terminate_succeeded);
    } else {
      LLDB_LOG(log,
               "NOT calling TerminateProcess because the inferior is not valid "
               "({0}, 0) (inferior={1})",
               handle, pid);
    }
  }

  // If we're stuck waiting for an exception to continue (e.g. the user is at a
  // breakpoint messing around in the debugger), continue it now.  But only
  // AFTER calling TerminateProcess to make sure that the very next call to
  // WaitForDebugEventEx is an exit process event.
  if (GetActiveException()) {
    LLDB_LOG(log, "masking active exception");
    ContinueAsyncException(ExceptionResult::MaskException);
  }

  ContinueAsyncDllEvent();

  if (!terminate) {
    // Indicate that we want to detach.
    m_pid_to_detach = GetProcess().GetProcessId();

    // Force a fresh break so that the detach can happen from the debugger
    // thread.
    if (!::DebugBreakProcess(
            GetProcess().GetNativeProcess().GetSystemHandle())) {
      error = Status(::GetLastError(), eErrorTypeWin32);
    }
  }

  LLDB_LOG(log, "waiting for detach from process {0} to complete.", pid);

  DWORD wait_result = WaitForSingleObject(m_debugging_ended_event, 5000);
  if (wait_result != WAIT_OBJECT_0) {
    error = Status(GetLastError(), eErrorTypeWin32);
    LLDB_LOG(log, "error: WaitForSingleObject({0}, 5000) returned {1}",
             m_debugging_ended_event, wait_result);
  } else
    LLDB_LOG(log, "detach from process {0} completed successfully.", pid);

  if (!error.Success()) {
    LLDB_LOG(log, "encountered an error while trying to stop process {0}. {1}",
             pid, error);
  }
  return error;
}

ExceptionRecordSP DebuggerThread::GetActiveException() {
  std::lock_guard<std::mutex> guard(m_active_exception_mutex);
  return m_active_exception;
}

void DebuggerThread::ContinueAsyncException(ExceptionResult result) {
  {
    std::lock_guard<std::mutex> guard(m_active_exception_mutex);
    if (!m_active_exception)
      return;
    m_active_exception.reset();
  }

  Log *log = GetLog(WindowsLog::Process | WindowsLog::Exception);
  LLDB_LOG(log, "broadcasting for inferior process {0}.",
           m_process.GetProcessId());

  m_exception_pred.SetValue(result, eBroadcastAlways);
}

void DebuggerThread::ContinueAsyncDllEvent() {
  m_dll_event_pred.SetValue(true, eBroadcastAlways);
}

void DebuggerThread::FreeProcessHandles() {
  m_process = HostProcess();
  m_main_thread = HostThread();
  if (m_image_file) {
    ::CloseHandle(m_image_file);
    m_image_file = nullptr;
  }
}

void DebuggerThread::DebugLoop() {
  Log *log = GetLog(WindowsLog::Event);
  DEBUG_EVENT dbe = {};
  bool should_debug = true;
  LLDB_LOG_VERBOSE(log, "Entering WaitForDebugEventEx loop");
  while (should_debug) {
    LLDB_LOG_VERBOSE(log, "Calling WaitForDebugEvent");
    BOOL wait_result = g_wait_for_debug_event(&dbe, INFINITE);
    if (wait_result) {
      DWORD continue_status = DBG_CONTINUE;
      bool shutting_down = m_is_shutting_down;
      switch (dbe.dwDebugEventCode) {
      default:
        llvm_unreachable("Unhandled debug event code!");
      case EXCEPTION_DEBUG_EVENT: {
        ExceptionResult status = HandleExceptionEvent(
            dbe.u.Exception, dbe.dwThreadId, shutting_down);

        if (status == ExceptionResult::MaskException)
          continue_status = DBG_CONTINUE;
        else if (status == ExceptionResult::SendToApplication)
          continue_status = DBG_EXCEPTION_NOT_HANDLED;

        break;
      }
      case CREATE_THREAD_DEBUG_EVENT:
        continue_status =
            HandleCreateThreadEvent(dbe.u.CreateThread, dbe.dwThreadId);
        break;
      case CREATE_PROCESS_DEBUG_EVENT:
        continue_status =
            HandleCreateProcessEvent(dbe.u.CreateProcessInfo, dbe.dwThreadId);
        break;
      case EXIT_THREAD_DEBUG_EVENT:
        continue_status =
            HandleExitThreadEvent(dbe.u.ExitThread, dbe.dwThreadId);
        break;
      case EXIT_PROCESS_DEBUG_EVENT:
        continue_status =
            HandleExitProcessEvent(dbe.u.ExitProcess, dbe.dwThreadId);
        should_debug = false;
        break;
      case LOAD_DLL_DEBUG_EVENT:
        continue_status = HandleLoadDllEvent(dbe.u.LoadDll, dbe.dwThreadId);
        break;
      case UNLOAD_DLL_DEBUG_EVENT:
        continue_status = HandleUnloadDllEvent(dbe.u.UnloadDll, dbe.dwThreadId);
        break;
      case OUTPUT_DEBUG_STRING_EVENT:
        continue_status = HandleODSEvent(dbe.u.DebugString, dbe.dwThreadId);
        break;
      case RIP_EVENT:
        continue_status = HandleRipEvent(dbe.u.RipInfo, dbe.dwThreadId);
        if (dbe.u.RipInfo.dwType == SLE_ERROR)
          should_debug = false;
        break;
      }

      LLDB_LOG_VERBOSE(
          log, "calling ContinueDebugEvent({0}, {1}, {2}) on thread {3}.",
          dbe.dwProcessId, dbe.dwThreadId, continue_status,
          ::GetCurrentThreadId());

      ::ContinueDebugEvent(dbe.dwProcessId, dbe.dwThreadId, continue_status);

      // We have to DebugActiveProcessStop after ContinueDebugEvent, otherwise
      // the target process will crash
      if (shutting_down) {
        // A breakpoint that occurs while `m_pid_to_detach` is non-zero is a
        // magic exception that we use simply to wake up the DebuggerThread so
        // that we can close out the debug loop.
        if (m_pid_to_detach != 0 &&
            (dbe.u.Exception.ExceptionRecord.ExceptionCode ==
                 EXCEPTION_BREAKPOINT ||
             dbe.u.Exception.ExceptionRecord.ExceptionCode ==
                 STATUS_WX86_BREAKPOINT)) {
          LLDB_LOG(log,
                   "Breakpoint exception is cue to detach from process {0:x}",
                   m_pid_to_detach.load());

          // detaching with leaving breakpoint exception event on the queue may
          // cause target process to crash so process events as possible since
          // target threads are running at this time, there is possibility to
          // have some breakpoint exception between last WaitForDebugEventEx and
          // DebugActiveProcessStop but ignore for now.
          while (g_wait_for_debug_event(&dbe, 0)) {
            continue_status = DBG_CONTINUE;
            if (dbe.dwDebugEventCode == EXCEPTION_DEBUG_EVENT &&
                !(dbe.u.Exception.ExceptionRecord.ExceptionCode ==
                      EXCEPTION_BREAKPOINT ||
                  dbe.u.Exception.ExceptionRecord.ExceptionCode ==
                      STATUS_WX86_BREAKPOINT ||
                  dbe.u.Exception.ExceptionRecord.ExceptionCode ==
                      EXCEPTION_SINGLE_STEP))
              continue_status = DBG_EXCEPTION_NOT_HANDLED;
            ::ContinueDebugEvent(dbe.dwProcessId, dbe.dwThreadId,
                                 continue_status);
          }

          ::DebugActiveProcessStop(m_pid_to_detach);
          m_detached = true;
        }
      }

      if (m_detached)
        should_debug = false;
    } else {
      LLDB_LOG(log, "returned FALSE from WaitForDebugEventEx.  Error = {0}",
               ::GetLastError());

      should_debug = false;
    }
  }
  FreeProcessHandles();

  LLDB_LOG(log, "WaitForDebugEventEx loop completed, exiting.");
  ::SetEvent(m_debugging_ended_event);
}

ExceptionResult
DebuggerThread::HandleExceptionEvent(const EXCEPTION_DEBUG_INFO &info,
                                     DWORD thread_id, bool shutting_down) {
  Log *log = GetLog(WindowsLog::Event | WindowsLog::Exception);
  if (shutting_down) {
    bool is_breakpoint =
        (info.ExceptionRecord.ExceptionCode == EXCEPTION_BREAKPOINT ||
         info.ExceptionRecord.ExceptionCode == STATUS_WX86_BREAKPOINT);

    // Don't perform any blocking operations while we're shutting down.  That
    // will cause TerminateProcess -> WaitForSingleObject to time out.
    // We should not send breakpoint exceptions to the application.
    return is_breakpoint ? ExceptionResult::MaskException
                         : ExceptionResult::SendToApplication;
  }

  bool first_chance = (info.dwFirstChance != 0);

  ExceptionRecordSP active_exception =
      std::make_shared<ExceptionRecord>(info.ExceptionRecord, thread_id);
  {
    std::lock_guard<std::mutex> guard(m_active_exception_mutex);
    m_active_exception = active_exception;
  }
  // Set this before calling the delegate. The delegate can wake up the thread
  // driving the debugger, and that thread can call ContinueAsyncException
  // before OnDebugException returns.
  m_exception_pred.SetValue(ExceptionResult::BreakInDebugger, eBroadcastNever);

  LLDB_LOG(log, "encountered {0} chance exception {1:x} on thread {2:x}",
           first_chance ? "first" : "second",
           info.ExceptionRecord.ExceptionCode, thread_id);

  ExceptionResult result =
      m_debug_delegate->OnDebugException(first_chance, *active_exception);
  // The delegate only says what to do, it never continues the exception. If the
  // result is not BreakInDebugger, continue it here, or the wait below never
  // ends. If the other thread already continued it, this does nothing and its
  // result is what the wait below returns.
  if (result != ExceptionResult::BreakInDebugger)
    ContinueAsyncException(result);

  LLDB_LOG(log, "waiting for ExceptionPred != BreakInDebugger");
  result = *m_exception_pred.WaitForValueNotEqualTo(
      ExceptionResult::BreakInDebugger);

  LLDB_LOG(log, "got ExceptionPred = {0}", (int)m_exception_pred.GetValue());
  return result;
}

DWORD
DebuggerThread::HandleCreateThreadEvent(const CREATE_THREAD_DEBUG_INFO &info,
                                        DWORD thread_id) {
  Log *log = GetLog(WindowsLog::Event | WindowsLog::Thread);
  LLDB_LOG(log, "Thread {0} spawned in process {1}", thread_id,
           m_process.GetProcessId());
  HostThread thread(info.hThread);
  thread.GetNativeThread().SetOwnsHandle(false);
  m_debug_delegate->OnCreateThread(thread);
  return DBG_CONTINUE;
}

/// Read the path the process was created with from its process parameters
/// (PEB::ProcessParameters->ImagePathName).
///
/// This keeps the subst drive, junction or symbolic link the process was
/// launched through.
static std::optional<std::string> GetImagePathFromPEB(HANDLE process) {
  // winternl.h declares NtQueryInformationProcess, but there is no import
  // library for it.
  static LazyImport<decltype(&::NtQueryInformationProcess)>
      s_query_information_process{L"ntdll.dll", "NtQueryInformationProcess"};
  if (!s_query_information_process)
    return std::nullopt;

  PROCESS_BASIC_INFORMATION pbi = {};
  if ((*s_query_information_process)(process, ProcessBasicInformation, &pbi,
                                     sizeof(pbi), nullptr) < 0 ||
      !pbi.PebBaseAddress)
    return std::nullopt;

  PEB peb = {};
  if (!::ReadProcessMemory(process, pbi.PebBaseAddress, &peb, sizeof(peb),
                           nullptr) ||
      !peb.ProcessParameters)
    return std::nullopt;

  RTL_USER_PROCESS_PARAMETERS params = {};
  if (!::ReadProcessMemory(process, peb.ProcessParameters, &params,
                           sizeof(params), nullptr) ||
      !params.ImagePathName.Buffer || params.ImagePathName.Length == 0)
    return std::nullopt;

  std::wstring wpath(params.ImagePathName.Length / sizeof(wchar_t), L'\0');
  if (!::ReadProcessMemory(process, params.ImagePathName.Buffer, wpath.data(),
                           params.ImagePathName.Length, nullptr))
    return std::nullopt;

  std::string path;
  if (!llvm::convertWideToUTF8(wpath, path))
    return std::nullopt;
  // A process launched through an extended-length path has the "\\?\" prefix.
  return StripExtendedLengthPrefix(path);
}

DWORD
DebuggerThread::HandleCreateProcessEvent(const CREATE_PROCESS_DEBUG_INFO &info,
                                         DWORD thread_id) {
  Log *log = GetLog(WindowsLog::Event | WindowsLog::Process);
  uint32_t process_id = ::GetProcessId(info.hProcess);

  LLDB_LOG(log, "process {0} spawned", process_id);

  std::string thread_name;
  llvm::raw_string_ostream name_stream(thread_name);
  name_stream << "lldb.plugin.process-windows.secondary[" << process_id << "]";
  llvm::set_thread_name(thread_name);

  // info.hProcess and info.hThread are closed automatically by Windows when
  // EXIT_PROCESS_DEBUG_EVENT is received.
  m_process = HostProcess(info.hProcess);
  static_cast<HostProcessWindows &>(m_process.GetNativeProcess())
      .SetOwnsHandle(false);
  m_main_thread = HostThread(info.hThread);
  m_main_thread.GetNativeThread().SetOwnsHandle(false);
  m_image_file = info.hFile;

  lldb::addr_t load_addr = reinterpret_cast<lldb::addr_t>(info.lpBaseOfImage);
  m_image_path = GetImagePathFromPEB(info.hProcess).value_or("");
  m_debug_delegate->OnDebuggerConnected(load_addr);

  return DBG_CONTINUE;
}

DWORD
DebuggerThread::HandleExitThreadEvent(const EXIT_THREAD_DEBUG_INFO &info,
                                      DWORD thread_id) {
  Log *log = GetLog(WindowsLog::Event | WindowsLog::Thread);
  LLDB_LOG(log, "Thread {0} exited with code {1} in process {2}", thread_id,
           info.dwExitCode, m_process.GetProcessId());
  m_debug_delegate->OnExitThread(thread_id, info.dwExitCode);
  return DBG_CONTINUE;
}

DWORD
DebuggerThread::HandleExitProcessEvent(const EXIT_PROCESS_DEBUG_INFO &info,
                                       DWORD thread_id) {
  Log *log = GetLog(WindowsLog::Event | WindowsLog::Thread);
  LLDB_LOG(log, "process {0} exited with code {1}", m_process.GetProcessId(),
           info.dwExitCode);

  m_debug_delegate->OnExitProcess(info.dwExitCode);

  return DBG_CONTINUE;
}

static std::optional<std::string>
ConvertNtDevicePathToDosPath(llvm::ArrayRef<wchar_t> nt_path) {
  Log *log = GetLog(WindowsLog::Event);

  llvm::SmallVector<wchar_t, MAX_PATH> vol_name(MAX_PATH);
  HANDLE vol_iter = ::FindFirstVolumeW(vol_name.data(), vol_name.size());
  if (vol_iter == INVALID_HANDLE_VALUE) {
    LLDB_LOG(log,
             "ConvertNtDevicePathToDosPath: FindFirstVolumeW failed, "
             "error={0}",
             ::GetLastError());
    return std::nullopt;
  }
  llvm::scope_exit close_iter([&] { ::FindVolumeClose(vol_iter); });

  do {
    // FindFirstVolumeW yields "\\?\Volume{GUID}\".
    // QueryDosDeviceW expects "Volume{GUID}".
    size_t vol_len = ::wcsnlen(vol_name.data(), vol_name.size());
    if (vol_len < 5 || vol_name[vol_len - 1] != L'\\')
      continue;

    vol_name[vol_len - 1] = L'\0'; // strip trailing '\' for QueryDosDeviceW
    llvm::SmallVector<wchar_t, MAX_PATH> dev_name(MAX_PATH);
    bool ok = ::QueryDosDeviceW(vol_name.data() + 4, // skip "\\?\"
                                dev_name.data(), dev_name.size());
    vol_name[vol_len - 1] = L'\\'; // restore
    if (!ok)
      continue;

    // Check that nt_path begins with this device name followed by '\'.
    size_t dev_len = ::wcsnlen(dev_name.data(), dev_name.size());
    if (dev_len == 0 || dev_len >= nt_path.size())
      continue;
    if (_wcsnicmp(nt_path.data(), dev_name.data(), dev_len) != 0)
      continue;
    if (nt_path[dev_len] != L'\\')
      continue;

    // Prefer a drive-letter/mount-point over the raw volume GUID path.
    llvm::ArrayRef<wchar_t> mount(vol_name.data(), vol_len);
    llvm::SmallVector<wchar_t> mount_names;
    DWORD names_size = 0;
    ::GetVolumePathNamesForVolumeNameW(vol_name.data(), nullptr, 0,
                                       &names_size);
    if (names_size > 1) {
      mount_names.resize(names_size);
      DWORD written = 0;
      if (::GetVolumePathNamesForVolumeNameW(
              vol_name.data(), mount_names.data(), names_size, &written) &&
          mount_names[0] != L'\0') {
        mount = llvm::ArrayRef<wchar_t>(
            mount_names.data(),
            ::wcsnlen(mount_names.data(), mount_names.size()));
      }
    }

    // Build the final path: mount point + rest of nt_path.
    llvm::SmallVector<wchar_t> dos_wide(mount.begin(), mount.end());
    if (!dos_wide.empty() && dos_wide.back() == L'\\')
      dos_wide.pop_back();
    dos_wide.append(nt_path.begin() + dev_len, nt_path.end());

    std::string result;
    llvm::convertWideToUTF8(std::wstring_view(dos_wide.data(), dos_wide.size()),
                            result);
    return result;
  } while (::FindNextVolumeW(vol_iter, vol_name.data(), vol_name.size()));

  LLDB_LOG(log, "ConvertNtDevicePathToDosPath: no matching volume found");
  return std::nullopt;
}

// Query the file name backing the mapping at `addr` in `process` and convert
// the resulting NT device path to a DOS path.
static std::optional<std::string> GetMappedFileDosPath(HANDLE process,
                                                       LPVOID addr) {
  std::vector<wchar_t> mapped_filename(MAX_PATH + 1);
  DWORD mapped_len = 0;
  while (mapped_filename.size() <= PATHCCH_MAX_CCH) {
    mapped_len = ::GetMappedFileNameW(process, addr, mapped_filename.data(),
                                      mapped_filename.size());
    if (mapped_len == 0)
      return std::nullopt;
    if (mapped_len < mapped_filename.size())
      break;
    mapped_filename.resize(mapped_filename.size() * 2);
  }
  return ConvertNtDevicePathToDosPath(
      llvm::ArrayRef<wchar_t>(mapped_filename.data(), mapped_len + 1));
}

static std::optional<std::string> GetFileNameFromHandleFallback(HANDLE hFile) {
  // Check that file is not empty as we cannot map a file with zero length.
  DWORD dwFileSizeHi = 0;
  DWORD dwFileSizeLo = ::GetFileSize(hFile, &dwFileSizeHi);
  if (dwFileSizeLo == 0 && dwFileSizeHi == 0)
    return std::nullopt;

  AutoHandle filemap(
      ::CreateFileMappingW(hFile, nullptr, PAGE_READONLY, 0, 1, nullptr),
      nullptr);
  if (!filemap.IsValid())
    return std::nullopt;

  auto view_deleter = [](void *pMem) { ::UnmapViewOfFile(pMem); };
  std::unique_ptr<void, decltype(view_deleter)> pMem(
      ::MapViewOfFile(filemap.get(), FILE_MAP_READ, 0, 0, 1), view_deleter);
  if (!pMem)
    return std::nullopt;

  return GetMappedFileDosPath(::GetCurrentProcess(), pMem.get());
}

/// The path the loader recorded for the module at \p base_addr, or nullopt if
/// the loader's module list has no entry for it yet.
static std::optional<std::string> GetLoaderModuleName(HANDLE process,
                                                      LPVOID base_addr) {
  std::vector<wchar_t> module_filename(MAX_PATH + 1);
  while (module_filename.size() <= PATHCCH_MAX_CCH) {
    DWORD len =
        ::GetModuleFileNameExW(process, reinterpret_cast<HMODULE>(base_addr),
                               module_filename.data(), module_filename.size());
    if (len == 0)
      return std::nullopt;
    if (len < module_filename.size()) {
      std::string path_utf8;
      llvm::convertWideToUTF8(std::wstring_view(module_filename.data(), len),
                              path_utf8);
      return path_utf8;
    }
    module_filename.resize(module_filename.size() * 2);
  }
  return std::nullopt;
}

// Determine how many bytes can be read at `addr` in `process` before crossing
// out of the committed memory region containing it. Returns 0 if the address is
// not within a committed region.
static SIZE_T BytesReadableAt(HANDLE process, LPCVOID addr) {
  MEMORY_BASIC_INFORMATION mbi{};
  if (!::VirtualQueryEx(process, addr, &mbi, sizeof(mbi)))
    return 0;
  if (mbi.State != MEM_COMMIT)
    return 0;
  uintptr_t region_end =
      reinterpret_cast<uintptr_t>(mbi.BaseAddress) + mbi.RegionSize;
  uintptr_t a = reinterpret_cast<uintptr_t>(addr);
  assert(a < region_end);
  return region_end - a;
}

static std::optional<std::string> ReadRemotePathStringW(HANDLE process,
                                                        LPCVOID addr) {
  SIZE_T limit = std::min<SIZE_T>(PATHCCH_MAX_CCH * sizeof(wchar_t),
                                  BytesReadableAt(process, addr));
  std::vector<wchar_t> buf;
  for (SIZE_T capacity = MAX_PATH * sizeof(wchar_t);; capacity *= 2) {
    SIZE_T to_read = std::min<SIZE_T>(capacity, limit);
    to_read &= ~SIZE_T(1); // round down to a wchar_t boundary
    if (to_read < sizeof(wchar_t))
      return std::nullopt;

    buf.resize(to_read / sizeof(wchar_t));
    SIZE_T bytes_read = 0;
    if (!::ReadProcessMemory(process, addr, buf.data(), to_read, &bytes_read))
      return std::nullopt;

    size_t max_chars = bytes_read / sizeof(wchar_t);
    size_t len = ::wcsnlen(buf.data(), max_chars);
    if (len < max_chars) { // found the null terminator
      if (len == 0)        // empty string
        return std::nullopt;
      std::string result;
      llvm::convertWideToUTF8(std::wstring_view(buf.data(), len), result);
      return result;
    }
    if (to_read >= limit) // read everything available without a terminator
      return std::nullopt;
  }
}

static std::optional<std::string> ReadRemotePathStringA(HANDLE process,
                                                        LPCVOID addr) {
  SIZE_T limit =
      std::min<SIZE_T>(PATHCCH_MAX_CCH, BytesReadableAt(process, addr));
  std::vector<char> buf;
  for (SIZE_T capacity = MAX_PATH;; capacity *= 2) {
    SIZE_T to_read = std::min<SIZE_T>(capacity, limit);
    if (to_read == 0)
      return std::nullopt;

    buf.resize(to_read);
    SIZE_T bytes_read = 0;
    if (!::ReadProcessMemory(process, addr, buf.data(), to_read, &bytes_read))
      return std::nullopt;

    size_t len = ::strnlen(buf.data(), bytes_read);
    if (len < bytes_read) { // found the null terminator
      if (len == 0)         // empty string
        return std::nullopt;
      return std::string(buf.data(), len);
    }
    if (to_read >= limit) // read everything available without a terminator
      return std::nullopt;
  }
}

// Resolve the LOAD_DLL_DEBUG_INFO::lpImageName field.
static std::optional<std::string>
GetFileNameFromImageNameField(HANDLE process, const LOAD_DLL_DEBUG_INFO &info) {
  if (info.lpImageName == nullptr)
    return std::nullopt;

  LPVOID string_addr = nullptr;
  SIZE_T bytes_read = 0;
  if (!::ReadProcessMemory(process, info.lpImageName, &string_addr,
                           sizeof(string_addr), &bytes_read) ||
      bytes_read != sizeof(string_addr))
    return std::nullopt;

  if (info.fUnicode)
    return ReadRemotePathStringW(process, string_addr);
  return ReadRemotePathStringA(process, string_addr);
}

DWORD
DebuggerThread::HandleLoadDllEvent(const LOAD_DLL_DEBUG_INFO &info,
                                   DWORD thread_id) {
  Log *log = GetLog(WindowsLog::Event);

  DllEventAction action = DllEventAction::ContinueDebugLoop;
  auto on_load_dll = [&](llvm::StringRef path) {
    FileSpec file_spec(path);
    ModuleSpec module_spec(file_spec);
    lldb::addr_t load_addr = reinterpret_cast<lldb::addr_t>(info.lpBaseOfDll);

    LLDB_LOG(log, "Inferior {0} - DLL '{1}' loaded at address {2:x}...",
             m_process.GetProcessId(), path, info.lpBaseOfDll);

    m_dll_event_pred.SetValue(false, eBroadcastNever);
    action = m_debug_delegate->OnLoadDll(module_spec, load_addr, thread_id);
  };

  HANDLE process = m_process.GetNativeProcess().GetSystemHandle();

  // Prefer the path the loader used for the DLL, which keeps the subst drive,
  // junction or symbolic link it was reached through.
  std::optional<std::string> loader_path =
      GetFileNameFromImageNameField(process, info);
  if (loader_path && !llvm::sys::path::is_absolute(
                         *loader_path, llvm::sys::path::Style::windows))
    loader_path.reset();
  if (!loader_path)
    loader_path = GetLoaderModuleName(process, info.lpBaseOfDll);
  if (loader_path)
    loader_path = StripExtendedLengthPrefix(*loader_path);

  // The file handle gives the resolved path, with the on-disk case.
  std::optional<std::string> file_path;
  if (info.hFile != nullptr) {
    std::vector<wchar_t> buffer(1);
    DWORD required_size =
        GetFinalPathNameByHandleW(info.hFile, &buffer[0], 0, VOLUME_NAME_DOS);
    if (required_size > 0) {
      buffer.resize(required_size + 1);
      GetFinalPathNameByHandleW(info.hFile, &buffer[0], required_size,
                                VOLUME_NAME_DOS);
      std::string path_str_utf8;
      llvm::convertWideToUTF8(buffer.data(), path_str_utf8);
      file_path = StripExtendedLengthPrefix(path_str_utf8);
    } else {
      file_path = GetFileNameFromHandleFallback(info.hFile);
    }
  }

  // The loader's path often differs from the on-disk one only in case (e.g.
  // C:\windows\System32\KERNEL32.DLL). If that's the case, keep the on disk
  // spelling.
  std::optional<std::string> resolved_path = loader_path;
  if (!resolved_path ||
      (file_path &&
       llvm::StringRef(*file_path).equals_insensitive(*resolved_path)))
    resolved_path = file_path;
  if (!resolved_path)
    resolved_path = GetFileNameFromImageNameField(process, info);
  if (!resolved_path)
    resolved_path = GetMappedFileDosPath(process, info.lpBaseOfDll);

  if (resolved_path)
    on_load_dll(*resolved_path);
  else
    LLDB_LOG(log,
             "Inferior {0} - could not resolve path for LOAD_DLL_DEBUG_EVENT "
             "(hFile={1}, base={2:x}, last error={3})",
             m_process.GetProcessId(), info.hFile, info.lpBaseOfDll,
             ::GetLastError());

  // Windows does not automatically close info.hFile, so we need to do it.
  if (info.hFile != nullptr)
    ::CloseHandle(info.hFile);

  if (action == DllEventAction::ParkDebugLoop && !m_is_shutting_down.load())
    m_dll_event_pred.WaitForValueEqualTo(true);
  return DBG_CONTINUE;
}

DWORD
DebuggerThread::HandleUnloadDllEvent(const UNLOAD_DLL_DEBUG_INFO &info,
                                     DWORD thread_id) {
  Log *log = GetLog(WindowsLog::Event);
  LLDB_LOG(log, "process {0} unloading DLL at addr {1:x}.",
           m_process.GetProcessId(), info.lpBaseOfDll);

  m_dll_event_pred.SetValue(false, eBroadcastNever);
  DllEventAction action = m_debug_delegate->OnUnloadDll(
      reinterpret_cast<lldb::addr_t>(info.lpBaseOfDll), thread_id);
  if (action == DllEventAction::ParkDebugLoop && !m_is_shutting_down.load())
    m_dll_event_pred.WaitForValueEqualTo(true);
  return DBG_CONTINUE;
}

DWORD
DebuggerThread::HandleODSEvent(const OUTPUT_DEBUG_STRING_INFO &info,
                               DWORD thread_id) {
  m_debug_delegate->OnDebugString(
      static_cast<lldb::addr_t>(
          reinterpret_cast<uintptr_t>(info.lpDebugStringData)),
      info.fUnicode == TRUE, info.nDebugStringLength);
  return DBG_CONTINUE;
}

DWORD
DebuggerThread::HandleRipEvent(const RIP_INFO &info, DWORD thread_id) {
  Log *log = GetLog(WindowsLog::Event);
  LLDB_LOG(log, "encountered error {0} (type={1}) in process {2} thread {3}",
           info.dwError, info.dwType, m_process.GetProcessId(), thread_id);

  Status error(info.dwError, eErrorTypeWin32);
  m_debug_delegate->OnDebuggerError(error, info.dwType);

  return DBG_CONTINUE;
}
