//===-- PlatformWindows.cpp -------------------------------------*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "PlatformWindows.h"

// C Includes
#include <stdio.h>
#if defined (_WIN32)
#include "lldb/Host/windows/windows.h"
#include <winsock2.h>
#endif

// C++ Includes
// Other libraries and framework includes
// Project includes
#include "lldb/Core/Error.h"
#include "lldb/Core/Debugger.h"
#include "lldb/Core/PluginManager.h"
#include "lldb/Host/HostInfo.h"
#include "lldb/Core/ModuleSpec.h"
#include "lldb/Core/Module.h"
#include "lldb/Breakpoint/BreakpointLocation.h"
#include "lldb/Breakpoint/BreakpointSite.h"
#include "lldb/Target/Process.h"

using namespace lldb;
using namespace lldb_private;

static uint32_t g_initialize_count = 0;

namespace
{
    class SupportedArchList
    {
    public:
        SupportedArchList()
        {
            AddArch(ArchSpec("i686-pc-windows"));
            AddArch(HostInfo::GetArchitecture(HostInfo::eArchKindDefault));
            AddArch(HostInfo::GetArchitecture(HostInfo::eArchKind32));
            AddArch(HostInfo::GetArchitecture(HostInfo::eArchKind64));
            AddArch(ArchSpec("i386-pc-windows"));
        }

        size_t Count() const { return m_archs.size(); }

        const ArchSpec& operator[](int idx) { return m_archs[idx]; }

    private:
        void AddArch(const ArchSpec& spec)
        {
            auto iter = std::find_if(
                m_archs.begin(), m_archs.end(), 
                [spec](const ArchSpec& rhs) { return spec.IsExactMatch(rhs); });
            if (iter != m_archs.end())
                return;
            if (spec.IsValid())
                m_archs.push_back(spec);
        }

        std::vector<ArchSpec> m_archs;
    };
} // 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 == false && arch && arch->IsValid())
    {
        const llvm::Triple &triple = arch->GetTriple();
        switch (triple.getVendor())
        {
        case llvm::Triple::PC:
            create = true;
            break;

        case llvm::Triple::UnknownArch:
            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();
}

lldb_private::ConstString
PlatformWindows::GetPluginNameStatic(bool is_host)
{
    if (is_host)
    {
        static ConstString g_host_name(Platform::GetHostPlatformName ());
        return g_host_name;
    }
    else
    {
        static ConstString g_remote_name("remote-windows");
        return g_remote_name;
    }
}

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

lldb_private::ConstString
PlatformWindows::GetPluginName()
{
    return GetPluginNameStatic(IsHost());
}

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

    if (g_initialize_count++ == 0)
    {
#if defined (_WIN32)
        WSADATA dummy;
        WSAStartup(MAKEWORD(2,2), &dummy);
        // 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( void )
{
    if (g_initialize_count > 0)
    {
        if (--g_initialize_count == 0)
        {
#ifdef _WIN32
            WSACleanup();
#endif
            PluginManager::UnregisterPlugin (PlatformWindows::CreateInstance);
        }
    }

    Platform::Terminate ();
}

//------------------------------------------------------------------
/// Default Constructor
//------------------------------------------------------------------
PlatformWindows::PlatformWindows (bool is_host) :
    Platform(is_host)
{
}

//------------------------------------------------------------------
/// Destructor.
///
/// The destructor is virtual since this class is designed to be
/// inherited from by the plug-in instance.
//------------------------------------------------------------------
PlatformWindows::~PlatformWindows() = default;

bool
PlatformWindows::GetModuleSpec (const FileSpec& module_file_spec,
                                const ArchSpec& arch,
                                ModuleSpec &module_spec)
{
    if (m_remote_platform_sp)
        return m_remote_platform_sp->GetModuleSpec (module_file_spec, arch, module_spec);

    return Platform::GetModuleSpec (module_file_spec, arch, module_spec);
}

Error
PlatformWindows::ResolveExecutable (const ModuleSpec &ms,
                                    lldb::ModuleSP &exe_module_sp,
                                    const FileSpecList *module_search_paths_ptr)
{
    Error error;
    // Nothing special to do here, just use the actual file and architecture

    char exe_path[PATH_MAX];
    ModuleSpec resolved_module_spec(ms);

    if (IsHost())
    {
        // if we cant resolve the executable loation based on the current path variables
        if (!resolved_module_spec.GetFileSpec().Exists())
        {
            resolved_module_spec.GetFileSpec().GetPath(exe_path, sizeof(exe_path));
            resolved_module_spec.GetFileSpec().SetFile(exe_path, true);
        }

        if (!resolved_module_spec.GetFileSpec().Exists())
            resolved_module_spec.GetFileSpec().ResolveExecutableLocation ();

        if (resolved_module_spec.GetFileSpec().Exists())
            error.Clear();
        else
        {
            ms.GetFileSpec().GetPath(exe_path, sizeof(exe_path));
            error.SetErrorStringWithFormat("unable to find executable for '%s'", exe_path);
        }
    }
    else
    {
        if (m_remote_platform_sp)
        {
            error = GetCachedExecutable (resolved_module_spec, exe_module_sp, nullptr, *m_remote_platform_sp);
        }
        else
        {
            // We may connect to a process and use the provided executable (Don't use local $PATH).
            if (resolved_module_spec.GetFileSpec().Exists())
                error.Clear();
            else
                error.SetErrorStringWithFormat("the platform is not currently connected, and '%s' doesn't exist in the system root.", exe_path);
        }
    }

    if (error.Success())
    {
        if (resolved_module_spec.GetArchitecture().IsValid())
        {
            error = ModuleList::GetSharedModule(resolved_module_spec,
                                                exe_module_sp,
                                                nullptr,
                                                nullptr,
                                                nullptr);

            if (!exe_module_sp || exe_module_sp->GetObjectFile() == nullptr)
            {
                exe_module_sp.reset();
                error.SetErrorStringWithFormat ("'%s' doesn't contain the architecture %s",
                                                resolved_module_spec.GetFileSpec().GetPath().c_str(),
                                                resolved_module_spec.GetArchitecture().GetArchitectureName());
            }
        }
        else
        {
            // No valid architecture was specified, ask the platform for
            // the architectures that we should be using (in the correct order)
            // and see if we can find a match that way
            StreamString arch_names;
            for (uint32_t idx = 0; GetSupportedArchitectureAtIndex (idx, resolved_module_spec.GetArchitecture()); ++idx)
            {
                error = ModuleList::GetSharedModule(resolved_module_spec,
                                                    exe_module_sp,
                                                    nullptr,
                                                    nullptr,
                                                    nullptr);
                // Did we find an executable using one of the
                if (error.Success())
                {
                    if (exe_module_sp && exe_module_sp->GetObjectFile())
                        break;
                    else
                        error.SetErrorToGenericError();
                }

                if (idx > 0)
                    arch_names.PutCString (", ");
                arch_names.PutCString (resolved_module_spec.GetArchitecture().GetArchitectureName());
            }

            if (error.Fail() || !exe_module_sp)
            {
                if (resolved_module_spec.GetFileSpec().Readable())
                {
                    error.SetErrorStringWithFormat ("'%s' doesn't contain any '%s' platform architectures: %s",
                                                    resolved_module_spec.GetFileSpec().GetPath().c_str(),
                                                    GetPluginName().GetCString(),
                                                    arch_names.GetString().c_str());
                }
                else
                {
                    error.SetErrorStringWithFormat("'%s' is not readable", resolved_module_spec.GetFileSpec().GetPath().c_str());
                }
            }
        }
    }

    return error;
}

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

    switch (arch.GetMachine())
    {
    case llvm::Triple::x86:
    case llvm::Triple::x86_64:
        {
            static const uint8_t g_i386_opcode[] = { 0xCC };
            trap_opcode = g_i386_opcode;
            trap_opcode_size = sizeof(g_i386_opcode);
        }
        break;

    case llvm::Triple::hexagon:
        {
            static const uint8_t g_hex_opcode[] = { 0x0c, 0xdb, 0x00, 0x54 };
            trap_opcode = g_hex_opcode;
            trap_opcode_size = sizeof(g_hex_opcode);
        }
        break;
    default:
        llvm_unreachable("Unhandled architecture in PlatformWindows::GetSoftwareBreakpointTrapOpcode()");
        break;
    }

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

    return 0;
}

bool
PlatformWindows::GetRemoteOSVersion ()
{
    if (m_remote_platform_sp)
        return m_remote_platform_sp->GetOSVersion (m_major_os_version,
                                                   m_minor_os_version,
                                                   m_update_os_version);
    return false;
}

bool
PlatformWindows::GetRemoteOSBuildString (std::string &s)
{
    if (m_remote_platform_sp)
        return m_remote_platform_sp->GetRemoteOSBuildString (s);
    s.clear();
    return false;
}

bool
PlatformWindows::GetRemoteOSKernelDescription (std::string &s)
{
    if (m_remote_platform_sp)
        return m_remote_platform_sp->GetRemoteOSKernelDescription (s);
    s.clear();
    return false;
}

// Remote Platform subclasses need to override this function
ArchSpec
PlatformWindows::GetRemoteSystemArchitecture ()
{
    if (m_remote_platform_sp)
        return m_remote_platform_sp->GetRemoteSystemArchitecture ();
    return ArchSpec();
}

const char *
PlatformWindows::GetHostname ()
{
    if (IsHost())
        return Platform::GetHostname();

    if (m_remote_platform_sp)
        return m_remote_platform_sp->GetHostname ();
    return nullptr;
}

bool
PlatformWindows::IsConnected () const
{
    if (IsHost())
        return true;
    else if (m_remote_platform_sp)
        return m_remote_platform_sp->IsConnected();
    return false;
}

Error
PlatformWindows::ConnectRemote (Args& args)
{
    Error error;
    if (IsHost())
    {
        error.SetErrorStringWithFormat ("can't connect to the host platform '%s', always connected", GetPluginName().AsCString() );
    }
    else
    {
        if (!m_remote_platform_sp)
            m_remote_platform_sp = Platform::Create (ConstString("remote-gdb-server"), error);

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

        if (error.Fail())
            m_remote_platform_sp.reset();
    }

    return error;
}

Error
PlatformWindows::DisconnectRemote ()
{
    Error error;

    if (IsHost())
    {
        error.SetErrorStringWithFormat ("can't disconnect from the host platform '%s', always connected", GetPluginName().AsCString() );
    }
    else
    {
        if (m_remote_platform_sp)
            error = m_remote_platform_sp->DisconnectRemote ();
        else
            error.SetErrorString ("the platform is not currently connected");
    }
    return error;
}

bool
PlatformWindows::GetProcessInfo (lldb::pid_t pid, ProcessInstanceInfo &process_info)
{
    bool success = false;
    if (IsHost())
    {
        success = Platform::GetProcessInfo (pid, process_info);
    }
    else if (m_remote_platform_sp)
    {
        success = m_remote_platform_sp->GetProcessInfo (pid, process_info);
    }
    return success;
}

uint32_t
PlatformWindows::FindProcesses (const ProcessInstanceInfoMatch &match_info,
                               ProcessInstanceInfoList &process_infos)
{
    uint32_t match_count = 0;
    if (IsHost())
    {
        // Let the base class figure out the host details
        match_count = Platform::FindProcesses (match_info, process_infos);
    }
    else
    {
        // If we are remote, we can only return results if we are connected
        if (m_remote_platform_sp)
            match_count = m_remote_platform_sp->FindProcesses (match_info, process_infos);
    }
    return match_count;
}

Error
PlatformWindows::LaunchProcess (ProcessLaunchInfo &launch_info)
{
    Error error;
    if (IsHost())
    {
        error = Platform::LaunchProcess (launch_info);
    }
    else
    {
        if (m_remote_platform_sp)
            error = m_remote_platform_sp->LaunchProcess (launch_info);
        else
            error.SetErrorString ("the platform is not currently connected");
    }
    return error;
}

ProcessSP
PlatformWindows::DebugProcess(ProcessLaunchInfo &launch_info, Debugger &debugger, Target *target, Error &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 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 (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);
    }
    else
    {
        ProcessSP process_sp = target->CreateProcess(launch_info.GetListenerForProcess(debugger),
                                                     launch_info.GetProcessPluginName(),
                                                     nullptr);

        // We need to launch and attach to the process.
        launch_info.GetFlags().Set(eLaunchFlagDebug);
        if (process_sp)
            error = process_sp->Launch(launch_info);

        return process_sp;
    }
}

lldb::ProcessSP
PlatformWindows::Attach(ProcessAttachInfo &attach_info,
                        Debugger &debugger,
                        Target *target,
                        Error &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.SetErrorString ("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,
                                                      nullptr,
                                                      nullptr,
                                                      false,
                                                      nullptr,
                                                      new_target_sp);
        target = new_target_sp.get();
    }

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

    debugger.GetTargetList().SetSelectedTarget(target);

    const char *plugin_name = attach_info.GetProcessPluginName();
    process_sp = target->CreateProcess(attach_info.GetListenerForProcess(debugger), plugin_name, nullptr);

    process_sp->HijackProcessEvents(attach_info.GetHijackListener().get());
    if (process_sp)
        error = process_sp->Attach (attach_info);

    return process_sp;
}

const char *
PlatformWindows::GetUserName (uint32_t uid)
{
    // Check the cache in Platform in case we have already looked this uid up
    const char *user_name = Platform::GetUserName(uid);
    if (user_name)
        return user_name;

    if (IsRemote() && m_remote_platform_sp)
        return m_remote_platform_sp->GetUserName(uid);
    return nullptr;
}

const char *
PlatformWindows::GetGroupName (uint32_t gid)
{
    const char *group_name = Platform::GetGroupName(gid);
    if (group_name)
        return group_name;

    if (IsRemote() && m_remote_platform_sp)
        return m_remote_platform_sp->GetGroupName(gid);
    return nullptr;
}

Error
PlatformWindows::GetFileWithUUID (const FileSpec &platform_file,
                                  const UUID *uuid_ptr,
                                  FileSpec &local_file)
{
    if (IsRemote())
    {
        if (m_remote_platform_sp)
            return m_remote_platform_sp->GetFileWithUUID (platform_file, uuid_ptr, local_file);
    }

    // Default to the local case
    local_file = platform_file;
    return Error();
}

Error
PlatformWindows::GetSharedModule (const ModuleSpec &module_spec,
                                  Process* process,
                                  ModuleSP &module_sp,
                                  const FileSpecList *module_search_paths_ptr,
                                  ModuleSP *old_module_sp_ptr,
                                  bool *did_create_ptr)
{
    Error error;
    module_sp.reset();

    if (IsRemote())
    {
        // If we have a remote platform always, let it try and locate
        // the shared module first.
        if (m_remote_platform_sp)
        {
            error = m_remote_platform_sp->GetSharedModule (module_spec,
                                                           process,
                                                           module_sp,
                                                           module_search_paths_ptr,
                                                           old_module_sp_ptr,
                                                           did_create_ptr);
        }
    }

    if (!module_sp)
    {
        // Fall back to the local platform and find the file locally
        error = Platform::GetSharedModule (module_spec,
                                           process,
                                           module_sp,
                                           module_search_paths_ptr,
                                           old_module_sp_ptr,
                                           did_create_ptr);
    }
    if (module_sp)
        module_sp->SetPlatformFileSpec(module_spec.GetFileSpec());
    return error;
}

bool
PlatformWindows::GetSupportedArchitectureAtIndex (uint32_t idx, ArchSpec &arch)
{
    static SupportedArchList architectures;

    if (idx >= architectures.Count())
        return false;
    arch = architectures[idx];
    return true;
}

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

#ifdef _WIN32
    uint32_t major;
    uint32_t minor;
    uint32_t update;
    if (!HostInfo::GetOSVersion(major, minor, update))
    {
        strm << "Windows";
        return;
    }

    strm << "Host: Windows " << major
         << '.' << minor
         << " Build: " << update << '\n';
#endif
}

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

size_t
PlatformWindows::GetEnvironment(StringList &env)
{
    if (IsRemote())
    {
        if (m_remote_platform_sp)
            return m_remote_platform_sp->GetEnvironment(env);
        return 0;
    }

    return Host::GetEnvironment(env);
}

ConstString
PlatformWindows::GetFullNameForDylib (ConstString basename)
{
    if (basename.IsEmpty())
        return basename;
    
    StreamString stream;
    stream.Printf("%s.dll", basename.GetCString());
    return ConstString(stream.GetData());
}
