//===-- 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/Target/MemoryRegionInfo.h"
#include "lldb/Target/Process.h"
#include "llvm/Support/ConvertUTF.h"
#include "llvm/Support/Error.h"

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

using namespace lldb;
using namespace lldb_private;

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

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

Status ProcessDebugger::HaltProcess(bool &caused_stop) {
  Log *log = GetLog(WindowsLog::Process);
  Status error;
  llvm::sys::ScopedLock lock(m_mutex);
  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() != MemoryRegionInfo::OptionalBool::eYes)
    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}", 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(MemoryRegionInfo::eNo);
      info.SetExecutable(MemoryRegionInfo::eNo);
      info.SetWritable(MemoryRegionInfo::eNo);
      info.SetMapped(MemoryRegionInfo::eNo);
      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 ? MemoryRegionInfo::eYes : MemoryRegionInfo::eNo);
    info.SetExecutable(executable ? MemoryRegionInfo::eYes
                                  : MemoryRegionInfo::eNo);
    info.SetWritable(writable ? MemoryRegionInfo::eYes : MemoryRegionInfo::eNo);
  } else {
    info.SetReadable(MemoryRegionInfo::eNo);
    info.SetExecutable(MemoryRegionInfo::eNo);
    info.SetWritable(MemoryRegionInfo::eNo);
  }

  // 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(MemoryRegionInfo::eYes);
  } 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(MemoryRegionInfo::eNo);
  }

  LLDB_LOGV(log,
            "Memory region info for address {0}: 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(exit_code, eErrorTypeWin32);
    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.GetExceptionCode(), record.GetExceptionAddress());
    return ExceptionResult::SendToApplication;
  }

  ExceptionResult result = ExceptionResult::SendToApplication;
  if ((record.GetExceptionCode() == EXCEPTION_BREAKPOINT ||
       record.GetExceptionCode() ==
           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
}

void ProcessDebugger::OnLoadDll(const ModuleSpec &module_spec,
                                lldb::addr_t module_addr) {
  // Do nothing by default
}

void ProcessDebugger::OnUnloadDll(lldb::addr_t module_addr) {
  // Do nothing by default
}

void ProcessDebugger::OnDebugString(const std::string &string) {}

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

  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
