//===-- 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 <cstdio>
#include <optional>
#if defined(_WIN32)
#include "lldb/Host/windows/windows.h"
#include <winsock2.h>
#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/Status.h"

#include "llvm/ADT/ScopeExit.h"
#include "llvm/Support/ConvertUTF.h"

using namespace lldb;
using namespace lldb_private;

LLDB_PLUGIN_DEFINE(PlatformWindows)

static uint32_t g_initialize_count = 0;

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

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) {
  Status error;
  if (IsHost()) {
    error = Status::FromErrorStringWithFormatv(
        "can't connect to the host platform '{0}', always connected",
        GetPluginName());
  } else {
    if (!m_remote_platform_sp)
      m_remote_platform_sp =
          platform_gdb_server::PlatformRemoteGDBServer::CreateInstance(
              /*force=*/true, nullptr);

    if (m_remote_platform_sp) {
      if (error.Success()) {
        if (m_remote_platform_sp) {
          error = m_remote_platform_sp->ConnectRemote(args);
        } else {
          error = Status::FromErrorString(
              "\"platform connect\" takes a single argument: <connect-url>");
        }
      }
    } else
      error = Status::FromErrorString(
          "failed to create a 'remote-gdb-server' platform");

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

  Status status;
  UtilityFunction *loader =
      process->GetLoadImageUtilityFunction(this, [&]() -> std::unique_ptr<UtilityFunction> {
        return MakeLoadImageUtilityFunction(context, status);
      });
  if (loader == nullptr)
    return LLDB_INVALID_IMAGE_TOKEN;

  FunctionCaller *invocation = loader->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 */
  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 */
  // FIXME(compnerd) should do something better for the length?
  // GetModuleFileNameA is likely limited to PATH_MAX rather than the NT path
  // limit.
  unsigned injected_length = 261;

  lldb::addr_t injected_module_path =
      process->AllocateMemory(injected_length + 1,
                              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);
  });

  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.SetIsForUtilityExpr(true);

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

  /* Read result */
  lldb::addr_t token = process->ReadPointerFromMemory(injected_result, status);
  if (status.Fail()) {
    error = Status::FromErrorStringWithFormat(
        "LoadLibrary error: could not read the result: %s", status.AsCString());
    return LLDB_INVALID_IMAGE_TOKEN;
  }

  if (!token) {
    // XXX(compnerd) should we use the compiler to get the sizeof(unsigned)?
    uint64_t error_code =
        process->ReadUnsignedIntegerFromMemory(injected_result + 2 * word_size + sizeof(unsigned),
                                               word_size, 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;
  }

  std::string module_path;
  process->ReadCStringFromMemory(injected_module_path, module_path, status);
  if (status.Fail()) {
    error = Status::FromErrorStringWithFormat(
        "LoadLibrary error: could not read module path: %s",
        status.AsCString());
    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_IMAGE_TOKEN)
    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);
  }

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

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

  // We need to launch and attach to the process.
  launch_info.GetFlags().Set(eLaunchFlagDebug);
  if (!process_sp)
    return nullptr;
  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;
    FileSpec emptyFileSpec;
    ArchSpec emptyArchSpec;

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

  process_sp->HijackProcessEvents(attach_info.GetHijackListener());
  if (process_sp)
    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; }

ConstString PlatformWindows::GetFullNameForDylib(ConstString basename) {
  if (basename.IsEmpty())
    return basename;

  StreamString stream;
  stream.Printf("%s.dll", basename.GetCString());
  return ConstString(stream.GetString());
}

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

std::unique_ptr<UtilityFunction>
PlatformWindows::MakeLoadImageUtilityFunction(ExecutionContext &context,
                                              Status &status) {
  // 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

// 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 GetModuleFileNameA(HMODULE hModule, LPSTR lpFilename, DWORD nSize);
/* __declspec(dllimport) */ uint32_t GetModuleFileNameA(void *, char *, 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;
  char *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) {
  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);
  if (result->ImageBase == nullptr)
    result->ErrorCode = GetLastError();
  else
    result->Length = GetModuleFileNameA(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());
    status = Status::FromErrorStringWithFormat(
        "LoadLibrary error: could not create utility function: %s",
        error.c_str());
    return nullptr;
  }

  TypeSystemClangSP scratch_ts_sp =
      ScratchTypeSystemClang::GetForTarget(target);
  if (!scratch_ts_sp)
    return nullptr;

  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()) {
    status = Status::FromErrorStringWithFormat(
        "LoadLibrary error: could not create function caller: %s",
        error.AsCString());
    return nullptr;
  }

  if (!utility->GetFunctionCaller()) {
    status = Status::FromErrorString(
        "LoadLibrary error: could not get function caller");
    return nullptr;
  }

  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 GetModuleFileNameA(HMODULE, LPSTR, DWORD);
/* __declspec(dllimport) */ uint32_t GetModuleFileNameA(void *, char *, 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());

  ExpressionResults result = UserExpression::Evaluate(
      context, options, expression, kLoaderDecls, value);
  if (result != eExpressionCompleted)
    return value ? value->GetError().Clone() : Status("unknown error");

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

  return Status();
}
