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

#include <chrono>
#include <cstdio>
#include <optional>
#if defined(_WIN32)
#include "lldb/Host/windows/windows.h"
#include <pathcch.h>
#include <winsock2.h>
#else
#define MAX_PATH 260
#define PATHCCH_MAX_CCH 0x8000
#endif

#include "Plugins/Platform/gdb-server/PlatformRemoteGDBServer.h"
#include "Plugins/TypeSystem/Clang/TypeSystemClang.h"
#include "lldb/Breakpoint/BreakpointLocation.h"
#include "lldb/Breakpoint/BreakpointSite.h"
#include "lldb/Core/Debugger.h"
#include "lldb/Core/Module.h"
#include "lldb/Core/PluginManager.h"
#include "lldb/Expression/DiagnosticManager.h"
#include "lldb/Expression/FunctionCaller.h"
#include "lldb/Expression/UserExpression.h"
#include "lldb/Expression/UtilityFunction.h"
#include "lldb/Host/HostInfo.h"
#include "lldb/Target/DynamicLoader.h"
#include "lldb/Target/Process.h"
#include "lldb/Utility/ErrorMessages.h"
#include "lldb/Utility/Status.h"

#include "llvm/ADT/ScopeExit.h"
#include "llvm/Support/ConvertUTF.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/FormatAdapters.h"
#include "llvm/Support/FormatVariadic.h"

using namespace lldb;
using namespace lldb_private;

LLDB_PLUGIN_DEFINE(PlatformWindows)

static uint32_t g_initialize_count = 0;

// Upper bound on the timeout used when running a utility expression with
// only one thread allowed to run. On expiry, RunThreadPlan retries with all
// threads, so this does not shorten the overall timeout.
static std::chrono::microseconds GetLoaderOneThreadTimeout(Process *process) {
  constexpr std::chrono::seconds preferred(5);
  return std::min<std::chrono::microseconds>(
      preferred,
      std::chrono::microseconds(process->GetUtilityExpressionTimeout()) / 2);
}

namespace {

#define LLDB_PROPERTIES_windows
#include "PlatformWindowsProperties.inc"

enum {
#define LLDB_PROPERTIES_windows
#include "PlatformWindowsPropertiesEnum.inc"
};

class PluginProperties : public Properties {
public:
  PluginProperties() {
    m_collection_sp = std::make_shared<OptionValueProperties>("windows");
    m_collection_sp->Initialize(g_windows_properties_def);
  }

  bool DisableDebugHeap() const {
    return GetPropertyAtIndexAs<bool>(ePropertyDisableDebugHeap, true);
  }
};

static PluginProperties &GetGlobalProperties() {
  static PluginProperties g_settings;
  return g_settings;
}

} // end of anonymous namespace

PlatformSP PlatformWindows::CreateInstance(bool force,
                                           const lldb_private::ArchSpec *arch) {
  // The only time we create an instance is when we are creating a remote
  // windows platform
  const bool is_host = false;

  bool create = force;
  if (!create && arch && arch->IsValid()) {
    const llvm::Triple &triple = arch->GetTriple();
    switch (triple.getVendor()) {
    case llvm::Triple::PC:
      create = true;
      break;

    case llvm::Triple::UnknownVendor:
      create = !arch->TripleVendorWasSpecified();
      break;

    default:
      break;
    }

    if (create) {
      switch (triple.getOS()) {
      case llvm::Triple::Win32:
        break;

      case llvm::Triple::UnknownOS:
        create = arch->TripleOSWasSpecified();
        break;

      default:
        create = false;
        break;
      }
    }
  }
  if (create)
    return PlatformSP(new PlatformWindows(is_host));
  return PlatformSP();
}

llvm::StringRef PlatformWindows::GetPluginDescriptionStatic(bool is_host) {
  return is_host ? "Local Windows user platform plug-in."
                 : "Remote Windows user platform plug-in.";
}

void PlatformWindows::DebuggerInitialize(Debugger &debugger) {
  if (!PluginManager::GetSettingForPlatformPlugin(debugger, "windows")) {
    PluginManager::CreateSettingForPlatformPlugin(
        debugger, GetGlobalProperties().GetValueProperties(),
        "Properties for the Windows platform plugin.",
        /*is_global_property=*/true);
  }
}

void PlatformWindows::Initialize() {
  Platform::Initialize();

  if (g_initialize_count++ == 0) {
#if defined(_WIN32)
    // Force a host flag to true for the default platform object.
    PlatformSP default_platform_sp(new PlatformWindows(true));
    default_platform_sp->SetSystemArchitecture(HostInfo::GetArchitecture());
    Platform::SetHostPlatform(default_platform_sp);
#endif
    PluginManager::RegisterPlugin(
        PlatformWindows::GetPluginNameStatic(false),
        PlatformWindows::GetPluginDescriptionStatic(false),
        PlatformWindows::CreateInstance, PlatformWindows::DebuggerInitialize);
  }
}

void PlatformWindows::Terminate() {
  if (g_initialize_count > 0) {
    if (--g_initialize_count == 0) {
      PluginManager::UnregisterPlugin(PlatformWindows::CreateInstance);
    }
  }

  Platform::Terminate();
}

/// Default Constructor
PlatformWindows::PlatformWindows(bool is_host) : RemoteAwarePlatform(is_host) {
  const auto &AddArch = [&](const ArchSpec &spec) {
    if (llvm::any_of(m_supported_architectures, [spec](const ArchSpec &rhs) {
          return spec.IsExactMatch(rhs);
        }))
      return;
    if (spec.IsValid())
      m_supported_architectures.push_back(spec);
  };
  AddArch(HostInfo::GetArchitecture(HostInfo::eArchKindDefault));
  AddArch(HostInfo::GetArchitecture(HostInfo::eArchKind32));
  AddArch(HostInfo::GetArchitecture(HostInfo::eArchKind64));
}

Status PlatformWindows::ConnectRemote(Args &args) {
  if (IsHost())
    return Status::FromErrorStringWithFormatv(
        "can't connect to the host platform '{0}', always connected",
        GetPluginName());

  if (!m_remote_platform_sp)
    m_remote_platform_sp =
        platform_gdb_server::PlatformRemoteGDBServer::CreateInstance(
            /*force=*/true, nullptr);

  if (!m_remote_platform_sp)
    return Status::FromErrorString(
        "failed to create a 'remote-gdb-server' platform");

  Status error = m_remote_platform_sp->ConnectRemote(args);
  if (error.Fail())
    m_remote_platform_sp.reset();

  return error;
}

uint32_t PlatformWindows::DoLoadImage(Process *process,
                                      const FileSpec &remote_file,
                                      const std::vector<std::string> *paths,
                                      Status &error, FileSpec *loaded_image) {
  DiagnosticManager diagnostics;

  if (loaded_image)
    loaded_image->Clear();

  ThreadSP thread = process->GetThreadList().GetExpressionExecutionThread();
  if (!thread) {
    error = Status::FromErrorString(
        "LoadLibrary error: no thread available to invoke LoadLibrary");
    return LLDB_INVALID_IMAGE_TOKEN;
  }

  ExecutionContext context;
  thread->CalculateExecutionContext(context);

  llvm::Expected<UtilityFunction &> loader_or_err =
      process->GetLoadImageUtilityFunction(
          this, [&]() { return MakeLoadImageUtilityFunction(context); });
  if (!loader_or_err) {
    error = Status::FromError(loader_or_err.takeError());
    return LLDB_INVALID_IMAGE_TOKEN;
  }

  FunctionCaller *invocation = loader_or_err->GetFunctionCaller();
  if (!invocation) {
    error = Status::FromErrorString(
        "LoadLibrary error: could not get function caller");
    return LLDB_INVALID_IMAGE_TOKEN;
  }

  /* Convert name */
  llvm::SmallVector<llvm::UTF16, 261> name;
  if (!llvm::convertUTF8ToUTF16String(remote_file.GetPath(), name)) {
    error = Status::FromErrorString(
        "LoadLibrary error: could not convert path to UCS2");
    return LLDB_INVALID_IMAGE_TOKEN;
  }
  name.emplace_back(L'\0');

  /* Inject name paramter into inferior */
  Status status;
  lldb::addr_t injected_name =
      process->AllocateMemory(name.size() * sizeof(llvm::UTF16),
                              ePermissionsReadable | ePermissionsWritable,
                              status);
  if (injected_name == LLDB_INVALID_ADDRESS) {
    error = Status::FromErrorStringWithFormat(
        "LoadLibrary error: unable to allocate memory for name: %s",
        status.AsCString());
    return LLDB_INVALID_IMAGE_TOKEN;
  }

  llvm::scope_exit name_cleanup(
      [process, injected_name]() { process->DeallocateMemory(injected_name); });

  process->WriteMemory(injected_name, name.data(),
                       name.size() * sizeof(llvm::UTF16), status);
  if (status.Fail()) {
    error = Status::FromErrorStringWithFormat(
        "LoadLibrary error: unable to write name: %s", status.AsCString());
    return LLDB_INVALID_IMAGE_TOKEN;
  }

  /* Inject paths parameter into inferior */
  lldb::addr_t injected_paths{0x0};
  std::optional<llvm::scope_exit<std::function<void()>>> paths_cleanup;
  if (paths) {
    llvm::SmallVector<llvm::UTF16, 261> search_paths;

    for (const auto &path : *paths) {
      if (path.empty())
        continue;

      llvm::SmallVector<llvm::UTF16, 261> buffer;
      if (!llvm::convertUTF8ToUTF16String(path, buffer))
        continue;

      search_paths.append(std::begin(buffer), std::end(buffer));
      search_paths.emplace_back(L'\0');
    }
    search_paths.emplace_back(L'\0');

    injected_paths =
        process->AllocateMemory(search_paths.size() * sizeof(llvm::UTF16),
                                ePermissionsReadable | ePermissionsWritable,
                                status);
    if (injected_paths == LLDB_INVALID_ADDRESS) {
      error = Status::FromErrorStringWithFormat(
          "LoadLibrary error: unable to allocate memory for paths: %s",
          status.AsCString());
      return LLDB_INVALID_IMAGE_TOKEN;
    }

    paths_cleanup.emplace([process, injected_paths]() {
      process->DeallocateMemory(injected_paths);
    });

    process->WriteMemory(injected_paths, search_paths.data(),
                         search_paths.size() * sizeof(llvm::UTF16), status);
    if (status.Fail()) {
      error = Status::FromErrorStringWithFormat(
          "LoadLibrary error: unable to write paths: %s", status.AsCString());
      return LLDB_INVALID_IMAGE_TOKEN;
    }
  }

  /* Inject wszModulePath into inferior */
  // Start with a MAX_PATH-sized buffer (enough for the vast majority of module
  // paths) and grow it on demand if GetModuleFileNameW reports truncation (see
  // the loop after the helper runs).
  unsigned injected_length = MAX_PATH;

  lldb::addr_t injected_module_path = process->AllocateMemory(
      (injected_length + 1) * sizeof(llvm::UTF16),
      ePermissionsReadable | ePermissionsWritable, status);
  if (injected_module_path == LLDB_INVALID_ADDRESS) {
    error = Status::FromErrorStringWithFormat(
        "LoadLibrary error: unable to allocate memory for module location: %s",
        status.AsCString());
    return LLDB_INVALID_IMAGE_TOKEN;
  }

  llvm::scope_exit injected_module_path_cleanup(
      [process, injected_module_path]() {
        process->DeallocateMemory(injected_module_path);
      });

  /* Inject __lldb_LoadLibraryResult into inferior */
  const uint32_t word_size = process->GetAddressByteSize();
  lldb::addr_t injected_result =
      process->AllocateMemory(3 * word_size,
                              ePermissionsReadable | ePermissionsWritable,
                              status);
  if (status.Fail()) {
    error = Status::FromErrorStringWithFormat(
        "LoadLibrary error: could not allocate memory for result: %s",
        status.AsCString());
    return LLDB_INVALID_IMAGE_TOKEN;
  }

  llvm::scope_exit result_cleanup([process, injected_result]() {
    process->DeallocateMemory(injected_result);
  });

  std::vector<lldb::addr_t> grown_path_buffers;
  llvm::scope_exit grown_path_cleanup([&]() {
    for (lldb::addr_t buffer : grown_path_buffers)
      process->DeallocateMemory(buffer);
  });

  process->WritePointerToMemory(injected_result, 0, status);
  if (status.Fail()) {
    error = Status::FromErrorStringWithFormat(
        "LoadLibrary error: could not initialize result: %s",
        status.AsCString());
    return LLDB_INVALID_IMAGE_TOKEN;
  }

  process->WritePointerToMemory(injected_result + word_size,
                                injected_module_path, status);
  if (status.Fail()) {
    error = Status::FromErrorStringWithFormat(
        "LoadLibrary error: could not initialize result: %s",
        status.AsCString());
    return LLDB_INVALID_IMAGE_TOKEN;
  }

  // XXX(compnerd) should we use the compiler to get the sizeof(unsigned)?
  process->WriteScalarToMemory(injected_result + 2 * word_size,
                               Scalar{injected_length}, sizeof(unsigned),
                               status);
  if (status.Fail()) {
    error = Status::FromErrorStringWithFormat(
        "LoadLibrary error: could not initialize result: %s",
        status.AsCString());
    return LLDB_INVALID_IMAGE_TOKEN;
  }

  /* Setup Formal Parameters */
  ValueList parameters = invocation->GetArgumentValues();
  parameters.GetValueAtIndex(0)->GetScalar() = injected_name;
  parameters.GetValueAtIndex(1)->GetScalar() = injected_paths;
  parameters.GetValueAtIndex(2)->GetScalar() = injected_result;

  lldb::addr_t injected_parameters = LLDB_INVALID_ADDRESS;
  diagnostics.Clear();
  if (!invocation->WriteFunctionArguments(context, injected_parameters,
                                          parameters, diagnostics)) {
    error = Status::FromError(diagnostics.GetAsError(
        eExpressionSetupError,
        "LoadLibrary error: unable to write function parameters:"));
    return LLDB_INVALID_IMAGE_TOKEN;
  }

  llvm::scope_exit parameter_cleanup(
      [invocation, &context, injected_parameters]() {
        invocation->DeallocateFunctionResults(context, injected_parameters);
      });

  TypeSystemClangSP scratch_ts_sp =
      ScratchTypeSystemClang::GetForTarget(process->GetTarget());
  if (!scratch_ts_sp) {
    error = Status::FromErrorString(
        "LoadLibrary error: unable to get (clang) type system");
    return LLDB_INVALID_IMAGE_TOKEN;
  }

  /* Setup Return Type */
  CompilerType VoidPtrTy =
      scratch_ts_sp->GetBasicType(eBasicTypeVoid).GetPointerType();

  Value value;
  value.SetCompilerType(VoidPtrTy);

  /* Invoke expression */
  EvaluateExpressionOptions options;
  options.SetExecutionPolicy(eExecutionPolicyAlways);
  options.SetLanguage(eLanguageTypeC_plus_plus);
  options.SetIgnoreBreakpoints(true);
  options.SetUnwindOnError(true);
  // LoadLibraryEx{A,W}/FreeLibrary cannot raise exceptions which we can handle.
  // They may potentially throw SEH exceptions which we do not know how to
  // handle currently.
  options.SetTrapExceptions(false);
  options.SetTimeout(process->GetUtilityExpressionTimeout());
  options.SetOneThreadTimeout(GetLoaderOneThreadTimeout(process));
  options.SetIsForUtilityExpr(true);

  ExpressionResults result =
      invocation->ExecuteFunction(context, &injected_parameters, options,
                                  diagnostics, value);
  if (result != eExpressionCompleted) {
    error = Status::FromError(diagnostics.GetAsError(
        eExpressionSetupError,
        llvm::formatv("failed to execute LoadLibrary helper "
                      "({0}):",
                      toString(result))
            .str()));
    return LLDB_INVALID_IMAGE_TOKEN;
  }

  /* Read result */
  llvm::Expected<lldb::addr_t> token_or_err =
      process->ReadPointerFromMemory(injected_result);
  if (!token_or_err) {
    error = Status::FromErrorStringWithFormatv(
        "LoadLibrary error: could not read the result: {0}",
        llvm::fmt_consume(token_or_err.takeError()));
    return LLDB_INVALID_IMAGE_TOKEN;
  }
  lldb::addr_t token = *token_or_err;

  if (!token) {
    // ErrorCode is a 4-byte `unsigned` field in __lldb_LoadLibraryResult.
    uint64_t error_code = process->ReadUnsignedIntegerFromMemory(
        injected_result + 2 * word_size + sizeof(unsigned), sizeof(unsigned), 0,
        status);
    if (status.Fail()) {
      error = Status::FromErrorStringWithFormat(
          "LoadLibrary error: could not read error status: %s",
          status.AsCString());
      return LLDB_INVALID_IMAGE_TOKEN;
    }

    error = Status::FromErrorStringWithFormat("LoadLibrary Error: %" PRIu64,
                                              error_code);
    return LLDB_INVALID_IMAGE_TOKEN;
  }

  lldb::addr_t module_path_addr = injected_module_path;
  unsigned capacity = injected_length;
  uint32_t path_length = process->ReadUnsignedIntegerFromMemory(
      injected_result + 2 * word_size, sizeof(unsigned), 0, status);
  while (status.Success() && path_length >= capacity &&
         capacity < PATHCCH_MAX_CCH) {
    capacity = std::min<unsigned>(capacity * 2, PATHCCH_MAX_CCH);
    lldb::addr_t buffer = process->AllocateMemory(
        (capacity + 1) * sizeof(llvm::UTF16),
        ePermissionsReadable | ePermissionsWritable, status);
    if (buffer == LLDB_INVALID_ADDRESS || status.Fail())
      break;
    grown_path_buffers.push_back(buffer);

    process->WritePointerToMemory(injected_result + word_size, buffer, status);
    if (status.Fail())
      break;
    process->WriteScalarToMemory(injected_result + 2 * word_size,
                                 Scalar{capacity}, sizeof(unsigned), status);
    if (status.Fail())
      break;

    diagnostics.Clear();
    if (invocation->ExecuteFunction(context, &injected_parameters, options,
                                    diagnostics, value) != eExpressionCompleted)
      break;
    module_path_addr = buffer;
    path_length = process->ReadUnsignedIntegerFromMemory(
        injected_result + 2 * word_size, sizeof(unsigned), 0, status);
  }

  llvm::SmallVector<llvm::UTF16, MAX_PATH> wide_path(path_length);
  if (path_length)
    process->ReadMemory(module_path_addr, wide_path.data(),
                        path_length * sizeof(llvm::UTF16), status);
  if (status.Fail()) {
    error = Status::FromErrorStringWithFormat(
        "LoadLibrary error: could not read module path: %s",
        status.AsCString());
    return LLDB_INVALID_IMAGE_TOKEN;
  }

  std::string module_path;
  if (!llvm::convertUTF16ToUTF8String(
          llvm::ArrayRef<llvm::UTF16>(wide_path.data(), wide_path.size()),
          module_path)) {
    error = Status::FromErrorString(
        "LoadLibrary error: could not convert module path to UTF-8");
    return LLDB_INVALID_IMAGE_TOKEN;
  }

  if (loaded_image)
    loaded_image->SetFile(module_path, llvm::sys::path::Style::native);
  return process->AddImageToken(token);
}

Status PlatformWindows::UnloadImage(Process *process, uint32_t image_token) {
  const addr_t address = process->GetImagePtrFromToken(image_token);
  if (address == LLDB_INVALID_ADDRESS)
    return Status::FromErrorString("invalid image token");

  StreamString expression;
  expression.Printf("FreeLibrary((HMODULE)0x%" PRIx64 ")", address);

  ValueObjectSP value;
  Status result =
      EvaluateLoaderExpression(process, expression.GetData(), value);
  if (result.Fail())
    return result;

  if (value->GetError().Fail())
    return value->GetError().Clone();

  Scalar scalar;
  if (value->ResolveValue(scalar)) {
    if (scalar.UInt(1))
      return Status::FromErrorStringWithFormat("expression failed: \"%s\"",
                                               expression.GetData());
    process->ResetImageToken(image_token);
  }

  return Status();
}

Status PlatformWindows::DisconnectRemote() {
  Status error;

  if (IsHost()) {
    error = Status::FromErrorStringWithFormatv(
        "can't disconnect from the host platform '{0}', always connected",
        GetPluginName());
  } else {
    if (m_remote_platform_sp)
      error = m_remote_platform_sp->DisconnectRemote();
    else
      error =
          Status::FromErrorString("the platform is not currently connected");
  }
  return error;
}

ProcessSP PlatformWindows::DebugProcess(ProcessLaunchInfo &launch_info,
                                        Debugger &debugger, Target &target,
                                        Status &error) {
  // Windows has special considerations that must be followed when launching or
  // attaching to a process.  The key requirement is that when launching or
  // attaching to a process, you must do it from the same the thread that will
  // go into a permanent loop which will then receive debug events from the
  // process.  In particular, this means we can't use any of LLDB's generic
  // mechanisms to do it for us, because it doesn't have the special knowledge
  // required for setting up the background thread or passing the right flags.
  //
  // Another problem is that LLDB's standard model for debugging a process
  // is to first launch it, have it stop at the entry point, and then attach to
  // it.  In Windows this doesn't quite work, you have to specify as an
  // argument to CreateProcess() that you're going to debug the process.  So we
  // override DebugProcess here to handle this.  Launch operations go directly
  // to the process plugin, and attach operations almost go directly to the
  // process plugin (but we hijack the events first).  In essence, we
  // encapsulate all the logic of Launching and Attaching in the process
  // plugin, and PlatformWindows::DebugProcess is just a pass-through to get to
  // the process plugin.

  if (IsRemote()) {
    if (m_remote_platform_sp)
      return m_remote_platform_sp->DebugProcess(launch_info, debugger, target,
                                                error);
    else
      error =
          Status::FromErrorString("the platform is not currently connected");
  }

  if (launch_info.GetProcessID() != LLDB_INVALID_PROCESS_ID) {
    // This is a process attach.  Don't need to launch anything.
    ProcessAttachInfo attach_info(launch_info);
    return Attach(attach_info, debugger, &target, error);
  }

  Environment &env = launch_info.GetEnvironment();
  if (GetGlobalProperties().DisableDebugHeap() &&
      !env.contains("_NO_DEBUG_HEAP")) {
    env.try_emplace("_NO_DEBUG_HEAP", "1");
  }

  ProcessSP process_sp =
      target.CreateProcess(launch_info.GetListener(),
                           launch_info.GetProcessPluginName(), nullptr, false);
  if (!process_sp)
    return nullptr;

  process_sp->HijackProcessEvents(launch_info.GetHijackListener());
  process_sp->SetShadowListener(launch_info.GetShadowListener());

  // We need to launch and attach to the process.
  launch_info.GetFlags().Set(eLaunchFlagDebug);
  error = process_sp->Launch(launch_info);
#ifdef _WIN32
  if (error.Success()) {
    process_sp->SetPseudoConsoleHandle();
  } else {
    Log *log = GetLog(LLDBLog::Platform);
    LLDB_LOGF(log, "Platform::%s LaunchProcess() failed: %s", __FUNCTION__,
              error.AsCString());
  }
#endif

  return process_sp;
}

lldb::ProcessSP PlatformWindows::Attach(ProcessAttachInfo &attach_info,
                                        Debugger &debugger, Target *target,
                                        Status &error) {
  error.Clear();
  lldb::ProcessSP process_sp;
  if (!IsHost()) {
    if (m_remote_platform_sp)
      process_sp =
          m_remote_platform_sp->Attach(attach_info, debugger, target, error);
    else
      error =
          Status::FromErrorString("the platform is not currently connected");
    return process_sp;
  }

  if (target == nullptr) {
    TargetSP new_target_sp;
    error = debugger.GetTargetList().CreateTarget(
        debugger, "", "", eLoadDependentsNo, nullptr, new_target_sp);
    target = new_target_sp.get();
  }

  if (!target || error.Fail())
    return process_sp;

  process_sp =
      target->CreateProcess(attach_info.GetListenerForProcess(debugger),
                            attach_info.GetProcessPluginName(), nullptr, false);

  if (process_sp) {
    process_sp->HijackProcessEvents(attach_info.GetHijackListener());
    process_sp->SetShadowListener(attach_info.GetShadowListener());
    error = process_sp->Attach(attach_info);
  }

  return process_sp;
}

void PlatformWindows::GetStatus(Stream &strm) {
  Platform::GetStatus(strm);

#ifdef _WIN32
  llvm::VersionTuple version = HostInfo::GetOSVersion();
  strm << "      Host: Windows " << version.getAsString() << '\n';
#endif
}

bool PlatformWindows::CanDebugProcess() { return true; }

std::string PlatformWindows::GetFullNameForDylib(llvm::StringRef basename) {
  if (basename.empty())
    return basename.str();

  return llvm::formatv("{0}.dll", basename).str();
}

size_t
PlatformWindows::GetSoftwareBreakpointTrapOpcode(Target &target,
                                                 BreakpointSite *bp_site) {
  ArchSpec arch = target.GetArchitecture();
  assert(arch.IsValid());
  const uint8_t *trap_opcode = nullptr;
  size_t trap_opcode_size = 0;

  switch (arch.GetMachine()) {
  case llvm::Triple::aarch64: {
    static const uint8_t g_aarch64_opcode[] = {0x00, 0x00, 0x3e, 0xd4}; // brk #0xf000
    trap_opcode = g_aarch64_opcode;
    trap_opcode_size = sizeof(g_aarch64_opcode);

    if (bp_site->SetTrapOpcode(trap_opcode, trap_opcode_size))
      return trap_opcode_size;
    return 0;
  } break;

  case llvm::Triple::arm:
  case llvm::Triple::thumb: {
    static const uint8_t g_thumb_opcode[] = {0xfe, 0xde}; // udf #0xfe
    trap_opcode = g_thumb_opcode;
    trap_opcode_size = sizeof(g_thumb_opcode);

    if (bp_site->SetTrapOpcode(trap_opcode, trap_opcode_size))
      return trap_opcode_size;
    return 0;
  } break;

  default:
    return Platform::GetSoftwareBreakpointTrapOpcode(target, bp_site);
  }
}

llvm::Expected<std::unique_ptr<UtilityFunction>>
PlatformWindows::MakeLoadImageUtilityFunction(ExecutionContext &context) {
  // FIXME(compnerd) `-fdeclspec` is not passed to the clang instance?
  static constexpr const char kLoaderDecls[] = R"(
extern "C" {
// errhandlingapi.h

// `LOAD_LIBRARY_SEARCH_APPLICATION_DIR | LOAD_LIBRARY_SEARCH_SYSTEM32 | LOAD_LIBRARY_SEARCH_USER_DIRS`
//
// Directories in the standard search path are not searched. This value cannot
// be combined with `LOAD_WITH_ALTERED_SEARCH_PATH`.
//
// This value represents the recommended maximum number of directories an
// application should include in its DLL search path.
#define LOAD_LIBRARY_SEARCH_DEFAULT_DIRS 0x00001000

// If this value is used, and lpFileName specifies an absolute path, the system
// uses the alternate file search strategy to find associated executable
// modules.
#define LOAD_WITH_ALTERED_SEARCH_PATH 0x00000008

// WINBASEAPI DWORD WINAPI GetLastError(VOID);
/* __declspec(dllimport) */ uint32_t __stdcall GetLastError();

// libloaderapi.h

// WINBASEAPI DLL_DIRECTORY_COOKIE WINAPI AddDllDirectory(LPCWSTR);
/* __declspec(dllimport) */ void * __stdcall AddDllDirectory(const wchar_t *);

// WINBASEAPI BOOL WINAPI FreeModule(HMODULE);
/* __declspec(dllimport) */ int __stdcall FreeModule(void *hLibModule);

// WINBASEAPI DWORD WINAPI GetModuleFileNameW(HMODULE hModule, LPWSTR lpFilename, DWORD nSize);
/* __declspec(dllimport) */ uint32_t GetModuleFileNameW(void *, wchar_t *, uint32_t);

// WINBASEAPI HMODULE WINAPI LoadLibraryExW(LPCWSTR, HANDLE, DWORD);
/* __declspec(dllimport) */ void * __stdcall LoadLibraryExW(const wchar_t *, void *, uint32_t);

// corecrt_wstring.h

// _ACRTIMP size_t __cdecl wcslen(wchar_t const *_String);
/* __declspec(dllimport) */ size_t __cdecl wcslen(const wchar_t *);

// lldb specific code

struct __lldb_LoadLibraryResult {
  void *ImageBase;
  wchar_t *ModulePath;
  unsigned Length;
  unsigned ErrorCode;
};

_Static_assert(sizeof(struct __lldb_LoadLibraryResult) <= 3 * sizeof(void *),
               "__lldb_LoadLibraryResult size mismatch");

void * __lldb_LoadLibraryHelper(const wchar_t *name, const wchar_t *paths,
                                __lldb_LoadLibraryResult *result) {
  // When the caller presets ImageBase the module is already loaded and we are
  // only re-querying its path with a larger buffer. Skip LoadLibrary in that
  // case so we do not take an extra reference on the module.
  if (result->ImageBase == nullptr) {
    for (const wchar_t *path = paths; path && *path; ) {
      (void)AddDllDirectory(path);
      path += wcslen(path) + 1;
    }

    result->ImageBase = LoadLibraryExW(name, nullptr,
                                       LOAD_LIBRARY_SEARCH_DEFAULT_DIRS);

    // Fallback: if the AddDllDirectory + LOAD_LIBRARY_SEARCH_DEFAULT_DIRS path
    // failed to find the library, iterate the search paths ourselves and
    // load by absolute path using LOAD_WITH_ALTERED_SEARCH_PATH, which makes
    // Windows use the loaded DLL's own directory to resolve its sibling imports.
    if (result->ImageBase == nullptr) {
      wchar_t full[4096];
      for (const wchar_t *path = paths; path && *path; path += wcslen(path) + 1) {
        size_t plen = wcslen(path);
        size_t nlen = wcslen(name);
        // Need room for: path + '\\' + name + '\0'
        if (plen + 1 + nlen + 1 > 4096)
          continue;
        wchar_t *p = full;
        for (size_t i = 0; i < plen; ++i)
          *p++ = path[i];
        *p++ = L'\\';
        for (size_t i = 0; i <= nlen; ++i) // Copy name including trailing '\0'.
          *p++ = name[i];
        result->ImageBase = LoadLibraryExW(full, nullptr,
                                           LOAD_WITH_ALTERED_SEARCH_PATH);
        if (result->ImageBase != nullptr)
          break;
      }
    }
  }

  if (result->ImageBase == nullptr)
    result->ErrorCode = GetLastError();
  else
    result->Length = GetModuleFileNameW(result->ImageBase, result->ModulePath,
                                        result->Length);

  return result->ImageBase;
}
}
  )";

  static constexpr const char kName[] = "__lldb_LoadLibraryHelper";

  ProcessSP process = context.GetProcessSP();
  Target &target = process->GetTarget();

  auto function = target.CreateUtilityFunction(std::string{kLoaderDecls}, kName,
                                               eLanguageTypeC_plus_plus,
                                               context);
  if (!function) {
    std::string error = llvm::toString(function.takeError());
    return llvm::createStringError(
        "LoadLibrary error: could not create utility function: %s",
        error.c_str());
  }

  TypeSystemClangSP scratch_ts_sp =
      ScratchTypeSystemClang::GetForTarget(target);
  if (!scratch_ts_sp)
    return llvm::createStringError("LoadLibrary error: no scratch type system");

  CompilerType VoidPtrTy =
      scratch_ts_sp->GetBasicType(eBasicTypeVoid).GetPointerType();
  CompilerType WCharPtrTy =
      scratch_ts_sp->GetBasicType(eBasicTypeWChar).GetPointerType();

  ValueList parameters;

  Value value;
  value.SetValueType(Value::ValueType::Scalar);

  value.SetCompilerType(WCharPtrTy);
  parameters.PushValue(value);  // name
  parameters.PushValue(value);  // paths

  value.SetCompilerType(VoidPtrTy);
  parameters.PushValue(value);  // result

  Status error;
  std::unique_ptr<UtilityFunction> utility{std::move(*function)};
  utility->MakeFunctionCaller(VoidPtrTy, parameters, context.GetThreadSP(),
                              error);
  if (error.Fail())
    return llvm::createStringError(
        "LoadLibrary error: could not create function caller: %s",
        error.AsCString());

  if (!utility->GetFunctionCaller())
    return llvm::createStringError(
        "LoadLibrary error: could not get function caller");

  return utility;
}

Status PlatformWindows::EvaluateLoaderExpression(Process *process,
                                                 const char *expression,
                                                 ValueObjectSP &value) {
  // FIXME(compnerd) `-fdeclspec` is not passed to the clang instance?
  static constexpr const char kLoaderDecls[] = R"(
extern "C" {
// libloaderapi.h

// WINBASEAPI DLL_DIRECTORY_COOKIE WINAPI AddDllDirectory(LPCWSTR);
/* __declspec(dllimport) */ void * __stdcall AddDllDirectory(const wchar_t *);

// WINBASEAPI BOOL WINAPI FreeModule(HMODULE);
/* __declspec(dllimport) */ int __stdcall FreeModule(void *);

// WINBASEAPI DWORD WINAPI GetModuleFileNameW(HMODULE, LPWSTR, DWORD);
/* __declspec(dllimport) */ uint32_t GetModuleFileNameW(void *, wchar_t *, uint32_t);

// WINBASEAPI HMODULE WINAPI LoadLibraryExW(LPCWSTR, HANDLE, DWORD);
/* __declspec(dllimport) */ void * __stdcall LoadLibraryExW(const wchar_t *, void *, uint32_t);
}
  )";

  if (DynamicLoader *loader = process->GetDynamicLoader()) {
    Status result = loader->CanLoadImage();
    if (result.Fail())
      return result;
  }

  ThreadSP thread = process->GetThreadList().GetExpressionExecutionThread();
  if (!thread)
    return Status::FromErrorString("selected thread is invalid");

  StackFrameSP frame = thread->GetStackFrameAtIndex(0);
  if (!frame)
    return Status::FromErrorString("frame 0 is invalid");

  ExecutionContext context;
  frame->CalculateExecutionContext(context);

  EvaluateExpressionOptions options;
  options.SetUnwindOnError(true);
  options.SetIgnoreBreakpoints(true);
  options.SetExecutionPolicy(eExecutionPolicyAlways);
  options.SetLanguage(eLanguageTypeC_plus_plus);
  // LoadLibraryEx{A,W}/FreeLibrary cannot raise exceptions which we can handle.
  // They may potentially throw SEH exceptions which we do not know how to
  // handle currently.
  options.SetTrapExceptions(false);
  options.SetTimeout(process->GetUtilityExpressionTimeout());
  options.SetOneThreadTimeout(GetLoaderOneThreadTimeout(process));

  ExpressionResults result = UserExpression::Evaluate(
      context, options, expression, kLoaderDecls, value);
  if (result != eExpressionCompleted)
    return value
               ? value->GetError().Clone()
               : Status::FromErrorStringWithFormatv(
                     "failed to execute loader helper ({0})", toString(result));

  if (value && value->GetError().Fail())
    return value->GetError().Clone();

  return Status();
}
