//===-- ProcessDebugger.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 "ProcessDebugger.h"

// Windows includes
#include "lldb/Host/windows/windows.h"
#include <psapi.h>

#include "lldb/Host/FileSystem.h"
#include "lldb/Host/HostNativeProcessBase.h"
#include "lldb/Host/HostProcess.h"
#include "lldb/Host/HostThread.h"
#include "lldb/Host/ProcessLaunchInfo.h"
#include "lldb/Host/windows/PathUtils.h"
#include "lldb/Target/MemoryRegionInfo.h"
#include "lldb/Target/Process.h"
#include "lldb/Utility/FileSpec.h"
#include "llvm/Support/ConvertUTF.h"
#include "llvm/Support/Error.h"

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

#include <string>
#include <string_view>

using namespace lldb;
using namespace lldb_private;

static void NormalizeWindowsPathSeparators(std::string &s) {
  for (char &c : s)
    if (c == '/')
      c = '\\';
}

bool ProcessDebugger::IsSystemDLL(llvm::StringRef path) {
  if (path.empty())
    return false;

  static const std::string windows_prefix = []() {
    std::string prefix;
    wchar_t buf[MAX_PATH];
    UINT len = ::GetWindowsDirectoryW(buf, MAX_PATH);
    if (len == 0 || len >= MAX_PATH)
      return prefix;
    llvm::convertWideToUTF8(std::wstring_view(buf, len), prefix);
    NormalizeWindowsPathSeparators(prefix);
    if (!prefix.empty() && prefix.back() != '\\')
      prefix += '\\';
    return prefix;
  }();

  if (windows_prefix.empty())
    return false;

  // A module loaded through an extended-length path has the "\\?\" prefix,
  // which would not match the Windows directory.
  std::string normalized = StripExtendedLengthPrefix(path);
  NormalizeWindowsPathSeparators(normalized);
  return llvm::StringRef(normalized).starts_with_insensitive(windows_prefix);
}

bool ProcessDebugger::IsSystemModuleAddress(lldb::addr_t addr) {
  if (!m_session_data || !m_session_data->m_debugger)
    return false;
  lldb::process_t handle = m_session_data->m_debugger->GetProcess()
                               .GetNativeProcess()
                               .GetSystemHandle();
  if (handle == nullptr || handle == LLDB_INVALID_PROCESS)
    return false;

  MEMORY_BASIC_INFORMATION mbi = {};
  if (::VirtualQueryEx(handle, reinterpret_cast<LPCVOID>(addr), &mbi,
                       sizeof(mbi)) != sizeof(mbi))
    return false;
  if (mbi.AllocationBase == nullptr)
    return false;

  // A truncated path still carries the leading directory, which is all
  // IsSystemDLL() inspects. MAX_PATH is enough.
  wchar_t module_path[MAX_PATH];
  DWORD len = ::GetModuleFileNameExW(
      handle, reinterpret_cast<HMODULE>(mbi.AllocationBase), module_path,
      MAX_PATH);
  if (len == 0)
    return false;

  std::string path_utf8;
  llvm::convertWideToUTF8(std::wstring_view(module_path, len), path_utf8);
  return IsSystemDLL(path_utf8);
}

static DWORD ConvertLldbToWinApiProtect(uint32_t protect) {
  // We also can process a read / write permissions here, but if the debugger
  // will make later a write into the allocated memory, it will fail. To get
  // around it is possible inside DoWriteMemory to remember memory permissions,
  // allow write, write and restore permissions, but for now we process only
  // the executable permission.
  //
  // TODO: Process permissions other than executable
  if (protect & ePermissionsExecutable)
    return PAGE_EXECUTE_READWRITE;

  return PAGE_READWRITE;
}

// The Windows page protection bits are NOT independent masks that can be
// bitwise-ORed together.  For example, PAGE_EXECUTE_READ is not (PAGE_EXECUTE
// | PAGE_READ).  To test for an access type, it's necessary to test for any of
// the bits that provide that access type.
static bool IsPageReadable(uint32_t protect) {
  return (protect & PAGE_NOACCESS) == 0;
}

static bool IsPageWritable(uint32_t protect) {
  return (protect & (PAGE_EXECUTE_READWRITE | PAGE_EXECUTE_WRITECOPY |
                     PAGE_READWRITE | PAGE_WRITECOPY)) != 0;
}

static bool IsPageExecutable(uint32_t protect) {
  return (protect & (PAGE_EXECUTE | PAGE_EXECUTE_READ | PAGE_EXECUTE_READWRITE |
                     PAGE_EXECUTE_WRITECOPY)) != 0;
}

namespace lldb_private {

ProcessDebugger::~ProcessDebugger() = default;

lldb::pid_t ProcessDebugger::GetDebuggedProcessId() const {
  if (m_session_data)
    return m_session_data->m_debugger->GetProcess().GetProcessId();
  return LLDB_INVALID_PROCESS_ID;
}

Status ProcessDebugger::DetachProcess() {
  Log *log = GetLog(WindowsLog::Process);
  DebuggerThreadSP debugger_thread;
  {
    // Acquire the lock only long enough to get the DebuggerThread.
    // StopDebugging() will trigger a call back into ProcessDebugger which will
    // also acquire the lock.  Thus we have to release the lock before calling
    // StopDebugging().
    llvm::sys::ScopedLock lock(m_mutex);

    if (!m_session_data) {
      LLDB_LOG(log, "there is no active session.");
      return Status();
    }

    debugger_thread = m_session_data->m_debugger;
  }

  Status error;

  LLDB_LOG(log, "detaching from process {0}.",
           debugger_thread->GetProcess().GetNativeProcess().GetSystemHandle());
  error = debugger_thread->StopDebugging(false);

  // By the time StopDebugging returns, there is no more debugger thread, so
  // we can be assured that no other thread will race for the session data.
  m_session_data.reset();

  return error;
}

Status ProcessDebugger::LaunchProcess(ProcessLaunchInfo &launch_info,
                                      DebugDelegateSP delegate) {
  // Even though m_session_data is accessed here, it is before a debugger
  // thread has been kicked off.  So there's no race conditions, and it
  // shouldn't be necessary to acquire the mutex.

  Log *log = GetLog(WindowsLog::Process);
  Status result;

  FileSpec working_dir = launch_info.GetWorkingDirectory();
  namespace fs = llvm::sys::fs;
  if (working_dir) {
    FileSystem::Instance().Resolve(working_dir);
    if (!FileSystem::Instance().IsDirectory(working_dir)) {
      result = Status::FromErrorStringWithFormat(
          "No such file or directory: %s", working_dir.GetPath().c_str());
      return result;
    }
  }

  if (!launch_info.GetFlags().Test(eLaunchFlagDebug)) {
    StreamString stream;
    stream.Printf("ProcessDebugger unable to launch '%s'.  ProcessDebugger can "
                  "only be used for debug launches.",
                  launch_info.GetExecutableFile().GetPath().c_str());
    std::string message = stream.GetString().str();
    result = Status::FromErrorString(message.c_str());

    LLDB_LOG(log, "error: {0}", message);
    return result;
  }

  bool stop_at_entry = launch_info.GetFlags().Test(eLaunchFlagStopAtEntry);
  m_session_data.reset(new ProcessWindowsData(stop_at_entry));
  m_session_data->m_debugger.reset(new DebuggerThread(delegate));
  DebuggerThreadSP debugger = m_session_data->m_debugger;

  // Kick off the DebugLaunch asynchronously and wait for it to complete.
  result = debugger->DebugLaunch(launch_info);
  if (result.Fail()) {
    LLDB_LOG(log, "failed launching '{0}'. {1}",
             launch_info.GetExecutableFile().GetPath(), result);
    return result;
  }

  HostProcess process;
  Status error = WaitForDebuggerConnection(debugger, process);
  if (error.Fail()) {
    LLDB_LOG(log, "failed launching '{0}'. {1}",
             launch_info.GetExecutableFile().GetPath(), error);
    return error;
  }

  LLDB_LOG(log, "successfully launched '{0}'",
           launch_info.GetExecutableFile().GetPath());

  // We've hit the initial stop.  If eLaunchFlagsStopAtEntry was specified, the
  // private state should already be set to eStateStopped as a result of
  // hitting the initial breakpoint.  If it was not set, the breakpoint should
  // have already been resumed from and the private state should already be
  // eStateRunning.
  launch_info.SetProcessID(process.GetProcessId());

  return result;
}

Status ProcessDebugger::AttachProcess(lldb::pid_t pid,
                                      const ProcessAttachInfo &attach_info,
                                      DebugDelegateSP delegate) {
  Log *log = GetLog(WindowsLog::Process);
  m_session_data.reset(
      new ProcessWindowsData(!attach_info.GetContinueOnceAttached()));
  DebuggerThreadSP debugger(new DebuggerThread(delegate));

  m_session_data->m_debugger = debugger;

  DWORD process_id = static_cast<DWORD>(pid);
  Status error = debugger->DebugAttach(process_id, attach_info);
  if (error.Fail()) {
    LLDB_LOG(
        log,
        "encountered an error occurred initiating the asynchronous attach. {0}",
        error);
    return error;
  }

  HostProcess process;
  error = WaitForDebuggerConnection(debugger, process);
  if (error.Fail()) {
    LLDB_LOG(log,
             "encountered an error waiting for the debugger to connect. {0}",
             error);
    return error;
  }

  LLDB_LOG(log, "successfully attached to process with pid={0}", process_id);

  // We've hit the initial stop.  If eLaunchFlagsStopAtEntry was specified, the
  // private state should already be set to eStateStopped as a result of
  // hitting the initial breakpoint.  If it was not set, the breakpoint should
  // have already been resumed from and the private state should already be
  // eStateRunning.

  return error;
}

Status ProcessDebugger::DestroyProcess(const lldb::StateType state) {
  Log *log = GetLog(WindowsLog::Process);
  DebuggerThreadSP debugger_thread;
  {
    // Acquire this lock inside an inner scope, only long enough to get the
    // DebuggerThread. StopDebugging() will trigger a call back into
    // ProcessDebugger which will acquire the lock again, so we need to not
    // deadlock.
    llvm::sys::ScopedLock lock(m_mutex);

    if (!m_session_data) {
      LLDB_LOG(log, "warning: state = {0}, but there is no active session.",
               state);
      return Status();
    }

    debugger_thread = m_session_data->m_debugger;
  }

  if (state == eStateExited || state == eStateDetached) {
    LLDB_LOG(log, "warning: cannot destroy process {0} while state = {1}.",
             GetDebuggedProcessId(), state);
    return Status();
  }

  LLDB_LOG(log, "Shutting down process {0}.",
           debugger_thread->GetProcess().GetNativeProcess().GetSystemHandle());
  auto error = debugger_thread->StopDebugging(true);

  // By the time StopDebugging returns, there is no more debugger thread, so
  // we can be assured that no other thread will race for the session data.
  m_session_data.reset();

  return error;
}

void ProcessDebugger::EndDebugSession() {
  DebuggerThreadSP debugger_thread;
  {
    llvm::sys::ScopedLock lock(m_mutex);
    if (!m_session_data)
      return;
    debugger_thread = m_session_data->m_debugger;
  }
  debugger_thread->StopDebugging(/*terminate=*/true);
  m_session_data.reset();
}

Status ProcessDebugger::HaltProcess(bool &caused_stop) {
  Log *log = GetLog(WindowsLog::Process);
  Status error;
  llvm::sys::ScopedLock lock(m_mutex);
  if (!m_session_data) {
    caused_stop = false;
    LLDB_LOG(log, "HaltProcess called with no active session.");
    return Status::FromErrorString(
        "HaltProcess called with no active debugger session.");
  }
  caused_stop = ::DebugBreakProcess(m_session_data->m_debugger->GetProcess()
                                        .GetNativeProcess()
                                        .GetSystemHandle());
  if (!caused_stop) {
    error = Status(::GetLastError(), eErrorTypeWin32);
    LLDB_LOG(log, "DebugBreakProcess failed with error {0}", error);
  }

  return error;
}

Status ProcessDebugger::ReadMemory(lldb::addr_t vm_addr, void *buf, size_t size,
                                   size_t &bytes_read) {
  Status error;
  bytes_read = 0;
  Log *log = GetLog(WindowsLog::Memory);
  llvm::sys::ScopedLock lock(m_mutex);

  if (!m_session_data) {
    error = Status::FromErrorString(
        "cannot read, there is no active debugger connection.");
    LLDB_LOG(log, "error: {0}", error);
    return error;
  }

  LLDB_LOG(log, "attempting to read {0} bytes from address {1:x}", size,
           vm_addr);

  lldb::process_t handle = m_session_data->m_debugger->GetProcess()
                               .GetNativeProcess()
                               .GetSystemHandle();
  void *addr = reinterpret_cast<void *>(vm_addr);
  SIZE_T num_of_bytes_read = 0;
  if (::ReadProcessMemory(handle, addr, buf, size, &num_of_bytes_read)) {
    bytes_read = num_of_bytes_read;
    return Status();
  }
  error = Status(GetLastError(), eErrorTypeWin32);
  MemoryRegionInfo info;
  if (GetMemoryRegionInfo(vm_addr, info).Fail() ||
      info.GetMapped() != eLazyBoolYes)
    return error;
  size = info.GetRange().GetRangeEnd() - vm_addr;
  LLDB_LOG(log, "retrying the read with size {0:x}", size);
  if (::ReadProcessMemory(handle, addr, buf, size, &num_of_bytes_read)) {
    LLDB_LOG(log, "success: read {0:x} bytes", num_of_bytes_read);
    bytes_read = num_of_bytes_read;
    return Status();
  }
  error = Status(GetLastError(), eErrorTypeWin32);
  LLDB_LOG(log, "error: {0}", error);
  return error;
}

Status ProcessDebugger::WriteMemory(lldb::addr_t vm_addr, const void *buf,
                                    size_t size, size_t &bytes_written) {
  Status error;
  bytes_written = 0;
  Log *log = GetLog(WindowsLog::Memory);
  llvm::sys::ScopedLock lock(m_mutex);
  LLDB_LOG(log, "attempting to write {0} bytes into address {1:x}", size,
           vm_addr);

  if (!m_session_data) {
    error = Status::FromErrorString(
        "cannot write, there is no active debugger connection.");
    LLDB_LOG(log, "error: {0}", error);
    return error;
  }

  HostProcess process = m_session_data->m_debugger->GetProcess();
  void *addr = reinterpret_cast<void *>(vm_addr);
  SIZE_T num_of_bytes_written = 0;
  lldb::process_t handle = process.GetNativeProcess().GetSystemHandle();
  if (::WriteProcessMemory(handle, addr, buf, size, &num_of_bytes_written)) {
    FlushInstructionCache(handle, addr, num_of_bytes_written);
    bytes_written = num_of_bytes_written;
  } else {
    error = Status(GetLastError(), eErrorTypeWin32);
    LLDB_LOG(log, "writing failed with error: {0}", error);
  }
  return error;
}

Status ProcessDebugger::AllocateMemory(size_t size, uint32_t permissions,
                                       lldb::addr_t &addr) {
  Status error;
  addr = LLDB_INVALID_ADDRESS;
  Log *log = GetLog(WindowsLog::Memory);
  llvm::sys::ScopedLock lock(m_mutex);
  LLDB_LOG(log, "attempting to allocate {0} bytes with permissions {1}", size,
           permissions);

  if (!m_session_data) {
    error = Status::FromErrorString(
        "cannot allocate, there is no active debugger connection");
    LLDB_LOG(log, "error: {0}", error);
    return error;
  }

  HostProcess process = m_session_data->m_debugger->GetProcess();
  lldb::process_t handle = process.GetNativeProcess().GetSystemHandle();
  auto protect = ConvertLldbToWinApiProtect(permissions);
  auto result = ::VirtualAllocEx(handle, nullptr, size, MEM_COMMIT, protect);
  if (!result) {
    error = Status(GetLastError(), eErrorTypeWin32);
    LLDB_LOG(log, "allocating failed with error: {0}", error);
  } else {
    addr = reinterpret_cast<addr_t>(result);
  }
  return error;
}

Status ProcessDebugger::DeallocateMemory(lldb::addr_t vm_addr) {
  Status result;

  Log *log = GetLog(WindowsLog::Memory);
  llvm::sys::ScopedLock lock(m_mutex);
  LLDB_LOG(log, "attempting to deallocate bytes at address {0:x}", vm_addr);

  if (!m_session_data) {
    result = Status::FromErrorString(
        "cannot deallocate, there is no active debugger connection");
    LLDB_LOG(log, "error: {0}", result);
    return result;
  }

  HostProcess process = m_session_data->m_debugger->GetProcess();
  lldb::process_t handle = process.GetNativeProcess().GetSystemHandle();
  if (!::VirtualFreeEx(handle, reinterpret_cast<LPVOID>(vm_addr), 0,
                       MEM_RELEASE)) {
    result = Status(GetLastError(), eErrorTypeWin32);
    LLDB_LOG(log, "deallocating failed with error: {0}", result);
  }

  return result;
}

Status ProcessDebugger::GetMemoryRegionInfo(lldb::addr_t vm_addr,
                                            MemoryRegionInfo &info) {
  Log *log = GetLog(WindowsLog::Memory);
  Status error;
  llvm::sys::ScopedLock lock(m_mutex);
  info.Clear();

  if (!m_session_data) {
    error = Status::FromErrorString(
        "GetMemoryRegionInfo called with no debugging session.");
    LLDB_LOG(log, "error: {0}", error);
    return error;
  }
  HostProcess process = m_session_data->m_debugger->GetProcess();
  lldb::process_t handle = process.GetNativeProcess().GetSystemHandle();
  if (handle == nullptr || handle == LLDB_INVALID_PROCESS) {
    error = Status::FromErrorString(
        "GetMemoryRegionInfo called with an invalid target process.");
    LLDB_LOG(log, "error: {0}", error);
    return error;
  }

  LLDB_LOG(log, "getting info for address {0:x}", vm_addr);

  void *addr = reinterpret_cast<void *>(vm_addr);
  MEMORY_BASIC_INFORMATION mem_info = {};
  SIZE_T result = ::VirtualQueryEx(handle, addr, &mem_info, sizeof(mem_info));
  if (result == 0) {
    DWORD last_error = ::GetLastError();
    if (last_error == ERROR_INVALID_PARAMETER) {
      // ERROR_INVALID_PARAMETER is returned if VirtualQueryEx is called with
      // an address past the highest accessible address. We should return a
      // range from the vm_addr to LLDB_INVALID_ADDRESS
      info.GetRange().SetRangeBase(vm_addr);
      info.GetRange().SetRangeEnd(LLDB_INVALID_ADDRESS);
      info.SetReadable(eLazyBoolNo);
      info.SetExecutable(eLazyBoolNo);
      info.SetWritable(eLazyBoolNo);
      info.SetMapped(eLazyBoolNo);
      return error;
    } else {
      error = Status(last_error, eErrorTypeWin32);
      LLDB_LOG(log,
               "VirtualQueryEx returned error {0} while getting memory "
               "region info for address {1:x}",
               error, vm_addr);
      return error;
    }
  }

  // Protect bits are only valid for MEM_COMMIT regions.
  if (mem_info.State == MEM_COMMIT) {
    const bool readable = IsPageReadable(mem_info.Protect);
    const bool executable = IsPageExecutable(mem_info.Protect);
    const bool writable = IsPageWritable(mem_info.Protect);
    info.SetReadable(readable ? eLazyBoolYes : eLazyBoolNo);
    info.SetExecutable(executable ? eLazyBoolYes : eLazyBoolNo);
    info.SetWritable(writable ? eLazyBoolYes : eLazyBoolNo);
  } else {
    info.SetReadable(eLazyBoolNo);
    info.SetExecutable(eLazyBoolNo);
    info.SetWritable(eLazyBoolNo);
  }

  // AllocationBase is defined for MEM_COMMIT and MEM_RESERVE but not MEM_FREE.
  if (mem_info.State != MEM_FREE) {
    info.GetRange().SetRangeBase(
        reinterpret_cast<addr_t>(mem_info.BaseAddress));
    info.GetRange().SetRangeEnd(reinterpret_cast<addr_t>(mem_info.BaseAddress) +
                                mem_info.RegionSize);
    info.SetMapped(eLazyBoolYes);
  } else {
    // In the unmapped case we need to return the distance to the next block of
    // memory. VirtualQueryEx nearly does that except that it gives the
    // distance from the start of the page containing vm_addr.
    SYSTEM_INFO data;
    ::GetSystemInfo(&data);
    DWORD page_offset = vm_addr % data.dwPageSize;
    info.GetRange().SetRangeBase(vm_addr);
    info.GetRange().SetByteSize(mem_info.RegionSize - page_offset);
    info.SetMapped(eLazyBoolNo);
  }

  LLDB_LOG_VERBOSE(log,
                   "Memory region info for address {0:x}: readable={1}, "
                   "executable={2}, writable={3}",
                   vm_addr, info.GetReadable(), info.GetExecutable(),
                   info.GetWritable());
  return error;
}

void ProcessDebugger::OnExitProcess(uint32_t exit_code) {
  // If the process exits before any initial stop then notify the debugger
  // of the error otherwise WaitForDebuggerConnection() will be blocked.
  // An example of this issue is when a process fails to load a dependent DLL.
  if (m_session_data && !m_session_data->m_initial_stop_received) {
    Status error = Status::FromErrorStringWithFormatv(
        "Process prematurely exited with {0:x}", exit_code);
    OnDebuggerError(error, 0);
  }
}

void ProcessDebugger::OnDebuggerConnected(lldb::addr_t image_base) {}

ExceptionResult
ProcessDebugger::OnDebugException(bool first_chance,
                                  const ExceptionRecord &record) {
  Log *log = GetLog(WindowsLog::Exception);
  llvm::sys::ScopedLock lock(m_mutex);
  // FIXME: Without this check, occasionally when running the test suite
  // there is an issue where m_session_data can be null.  It's not clear how
  // this could happen but it only surfaces while running the test suite.  In
  // order to properly diagnose this, we probably need to first figure allow the
  // test suite to print out full lldb logs, and then add logging to the process
  // plugin.
  if (!m_session_data) {
    LLDB_LOG(log,
             "Debugger thread reported exception {0:x} at address {1:x}, but "
             "there is no session.",
             record.GetExceptionValue(), record.GetExceptionAddress());
    return ExceptionResult::SendToApplication;
  }

  ExceptionResult result = ExceptionResult::SendToApplication;
  if ((record.GetExceptionValue() == EXCEPTION_BREAKPOINT ||
       record.GetExceptionValue() ==
           0x4000001FL /*WOW64 STATUS_WX86_BREAKPOINT*/) &&
      !m_session_data->m_initial_stop_received) {
    // Handle breakpoints at the first chance.
    result = ExceptionResult::BreakInDebugger;
    LLDB_LOG(
        log,
        "Hit loader breakpoint at address {0:x}, setting initial stop event.",
        record.GetExceptionAddress());
    m_session_data->m_initial_stop_received = true;
    ::SetEvent(m_session_data->m_initial_stop_event);
  }
  return result;
}

void ProcessDebugger::OnCreateThread(const HostThread &thread) {
  // Do nothing by default
}

void ProcessDebugger::OnExitThread(lldb::tid_t thread_id, uint32_t exit_code) {
  // Do nothing by default
}

DllEventAction ProcessDebugger::OnLoadDll(const ModuleSpec &module_spec,
                                          lldb::addr_t module_addr,
                                          lldb::tid_t thread_id) {
  return DllEventAction::ContinueDebugLoop;
}

DllEventAction ProcessDebugger::OnUnloadDll(lldb::addr_t module_addr,
                                            lldb::tid_t thread_id) {
  return DllEventAction::ContinueDebugLoop;
}

void ProcessDebugger::OnDebugString(lldb::addr_t debug_string_addr,
                                    bool is_unicode,
                                    uint16_t length_lower_word) {
  // Do nothing by default
}

llvm::Error
ProcessDebugger::ReadDebugString(lldb::addr_t debug_string_addr,
                                 bool is_unicode, uint16_t length_lower_word,
                                 llvm::SmallVectorImpl<char> &output) {
  if (is_unicode && length_lower_word % 2 != 0)
    return llvm::createStringError(
        "Utf16 string can't have uneven size in bytes");

  const auto is_zero_terminated = [&] {
    // The zero terminator is always at the end of the buffer.
    if (is_unicode)
      return output.size() >= 2 && output.back() == 0 &&
             output[output.size() - 2] == 0;

    return !output.empty() && output.back() == 0;
  };

  // Read at most 1 MiB ((1 << 16) * 16 - 1 Bytes) since we don't know the exact
  // size of the string. We know that `strlen(string) & 0xffff ==
  // length_lower_word`, so we read in chunks until we reach the terminator:
  // - 0: `length_lower_word` Bytes
  // - 1..16: 64 KiB (= 2^16 Bytes)
  size_t start = length_lower_word == 0 ? 1 : 0;
  for (size_t i = start; i < 16; ++i) {
    output.resize_for_overwrite(length_lower_word + i * (1 << 16));
    size_t chunk_size = i == 0 ? length_lower_word : (1 << 16);
    lldb::addr_t addr = debug_string_addr + output.size_in_bytes() - chunk_size;

    size_t bytes_read = 0;
    Status error =
        ReadMemory(addr, output.end() - chunk_size, chunk_size, bytes_read);
    if (error.Fail())
      return error.takeError();

    if (bytes_read != chunk_size) {
      return llvm::createStringErrorV(
          "Expected to read {0} bytes, but read {1}", chunk_size, bytes_read);
    }

    if (is_zero_terminated())
      break;
  }

  if (!is_zero_terminated())
    return llvm::createStringError("String is 1 MiB or larger");

  // Remove null terminator.
  output.pop_back_n(is_unicode ? 2 : 1);
  return llvm::Error::success();
}

void ProcessDebugger::OnDebuggerError(const Status &error, uint32_t type) {
  llvm::sys::ScopedLock lock(m_mutex);
  Log *log = GetLog(WindowsLog::Process);

  if (!m_session_data) {
    LLDB_LOG(log,
             "OnDebuggerError called with no active session: error {0}: {1}",
             error.GetError(), error);
    return;
  }

  if (m_session_data->m_initial_stop_received) {
    // This happened while debugging.  Do we shutdown the debugging session,
    // try to continue, or do something else?
    LLDB_LOG(log,
             "Error {0} occurred during debugging.  Unexpected behavior "
             "may result.  {1}",
             error.GetError(), error);
  } else {
    // If we haven't actually launched the process yet, this was an error
    // launching the process.  Set the internal error and signal the initial
    // stop event so that the DoLaunch method wakes up and returns a failure.
    m_session_data->m_launch_error = error.Clone();
    ::SetEvent(m_session_data->m_initial_stop_event);
    LLDB_LOG(log,
             "Error {0} occurred launching the process before the initial "
             "stop. {1}",
             error.GetError(), error);
    return;
  }
}

Status ProcessDebugger::WaitForDebuggerConnection(DebuggerThreadSP debugger,
                                                  HostProcess &process) {
  Status result;
  Log *log = GetLog(WindowsLog::Process | WindowsLog::Breakpoints);
  LLDB_LOG(log, "Waiting for loader breakpoint.");

  // Block this function until we receive the initial stop from the process.
  if (::WaitForSingleObject(m_session_data->m_initial_stop_event, INFINITE) ==
      WAIT_OBJECT_0) {
    LLDB_LOG(log, "hit loader breakpoint, returning.");

    process = debugger->GetProcess();
    return m_session_data->m_launch_error.Clone();
  } else
    return Status(::GetLastError(), eErrorTypeWin32);
}

} // namespace lldb_private
