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

#include "PlatformRemoteGDBServer.h"
#include "lldb/Host/Config.h"

// C++ Includes
// Other libraries and framework includes
// Project includes
#include "lldb/Breakpoint/BreakpointLocation.h"
#include "lldb/Core/Debugger.h"
#include "lldb/Core/Error.h"
#include "lldb/Core/Log.h"
#include "lldb/Core/Module.h"
#include "lldb/Core/ModuleList.h"
#include "lldb/Core/ModuleSpec.h"
#include "lldb/Core/PluginManager.h"
#include "lldb/Core/StreamFile.h"
#include "lldb/Core/StreamString.h"
#include "lldb/Host/ConnectionFileDescriptor.h"
#include "lldb/Host/FileSpec.h"
#include "lldb/Host/Host.h"
#include "lldb/Host/HostInfo.h"
#include "lldb/Host/StringConvert.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/Target.h"

#include "Utility/UriParser.h"

#include "Plugins/Process/Utility/GDBRemoteSignals.h"

using namespace lldb;
using namespace lldb_private;
using namespace lldb_private::platform_gdb_server;

static bool g_initialized = false;

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

    if (g_initialized == false)
    {
        g_initialized = true;
        PluginManager::RegisterPlugin (PlatformRemoteGDBServer::GetPluginNameStatic(),
                                       PlatformRemoteGDBServer::GetDescriptionStatic(),
                                       PlatformRemoteGDBServer::CreateInstance);
    }
}

void
PlatformRemoteGDBServer::Terminate ()
{
    if (g_initialized)
    {
        g_initialized = false;
        PluginManager::UnregisterPlugin (PlatformRemoteGDBServer::CreateInstance);
    }

    Platform::Terminate ();
}

PlatformSP
PlatformRemoteGDBServer::CreateInstance (bool force, const ArchSpec *arch)
{
    bool create = force;
    if (!create)
    {
        create = !arch->TripleVendorWasSpecified() && !arch->TripleOSWasSpecified();
    }
    if (create)
        return PlatformSP(new PlatformRemoteGDBServer());
    return PlatformSP();
}


ConstString
PlatformRemoteGDBServer::GetPluginNameStatic()
{
    static ConstString g_name("remote-gdb-server");
    return g_name;
}

const char *
PlatformRemoteGDBServer::GetDescriptionStatic()
{
    return "A platform that uses the GDB remote protocol as the communication transport.";
}

const char *
PlatformRemoteGDBServer::GetDescription ()
{
    if (m_platform_description.empty())
    {
        if (IsConnected())
        {
            // Send the get description packet
        }
    }
    
    if (!m_platform_description.empty())
        return m_platform_description.c_str();
    return GetDescriptionStatic();
}

Error
PlatformRemoteGDBServer::ResolveExecutable (const ModuleSpec &module_spec,
                                            lldb::ModuleSP &exe_module_sp,
                                            const FileSpecList *module_search_paths_ptr)
{
    // copied from PlatformRemoteiOS

    Error error;
    // Nothing special to do here, just use the actual file and architecture

    ModuleSpec resolved_module_spec(module_spec);

    // Resolve any executable within an apk on Android?
    //Host::ResolveExecutableInBundle (resolved_module_spec.GetFileSpec());

    if (resolved_module_spec.GetFileSpec().Exists() ||
        module_spec.GetUUID().IsValid())
    {
        if (resolved_module_spec.GetArchitecture().IsValid() || resolved_module_spec.GetUUID().IsValid())
        {
            error = ModuleList::GetSharedModule (resolved_module_spec,
                                                 exe_module_sp,
                                                 module_search_paths_ptr,
                                                 NULL,
                                                 NULL);

            if (exe_module_sp && exe_module_sp->GetObjectFile())
                return error;
            exe_module_sp.reset();
        }
        // No valid architecture was specified or the exact arch wasn't
        // found so 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,
                                                 module_search_paths_ptr,
                                                 NULL,
                                                 NULL);
            // 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());
            }
        }
    }
    else
    {
        error.SetErrorStringWithFormat ("'%s' does not exist",
                                        resolved_module_spec.GetFileSpec().GetPath().c_str());
    }

    return error;
}

bool
PlatformRemoteGDBServer::GetModuleSpec (const FileSpec& module_file_spec,
                                        const ArchSpec& arch,
                                        ModuleSpec &module_spec)
{
    Log *log = GetLogIfAnyCategoriesSet (LIBLLDB_LOG_PLATFORM);

    const auto module_path = module_file_spec.GetPath (false);

    if (!m_gdb_client.GetModuleInfo (module_file_spec, arch, module_spec))
    {
        if (log)
            log->Printf ("PlatformRemoteGDBServer::%s - failed to get module info for %s:%s",
                         __FUNCTION__, module_path.c_str (), arch.GetTriple ().getTriple ().c_str ());
        return false;
    }

    if (log)
    {
        StreamString stream;
        module_spec.Dump (stream);
        log->Printf ("PlatformRemoteGDBServer::%s - got module info for (%s:%s) : %s",
                     __FUNCTION__, module_path.c_str (), arch.GetTriple ().getTriple ().c_str (), stream.GetString ().c_str ());
    }

    return true;
}

Error
PlatformRemoteGDBServer::GetFileWithUUID (const FileSpec &platform_file, 
                                          const UUID *uuid_ptr,
                                          FileSpec &local_file)
{
    // Default to the local case
    local_file = platform_file;
    return Error();
}

//------------------------------------------------------------------
/// Default Constructor
//------------------------------------------------------------------
PlatformRemoteGDBServer::PlatformRemoteGDBServer () :
    Platform (false), // This is a remote platform
    m_gdb_client ()
{
}

//------------------------------------------------------------------
/// Destructor.
///
/// The destructor is virtual since this class is designed to be
/// inherited from by the plug-in instance.
//------------------------------------------------------------------
PlatformRemoteGDBServer::~PlatformRemoteGDBServer()
{
}

bool
PlatformRemoteGDBServer::GetSupportedArchitectureAtIndex (uint32_t idx, ArchSpec &arch)
{
    ArchSpec remote_arch = m_gdb_client.GetSystemArchitecture();

    if (idx == 0)
    {
        arch = remote_arch;
        return arch.IsValid();
    }
    else if (idx == 1 && remote_arch.IsValid() && remote_arch.GetTriple().isArch64Bit())
    {
        arch.SetTriple(remote_arch.GetTriple().get32BitArchVariant());
        return arch.IsValid();
    }
    return false;
}

size_t
PlatformRemoteGDBServer::GetSoftwareBreakpointTrapOpcode (Target &target, BreakpointSite *bp_site)
{
    // This isn't needed if the z/Z packets are supported in the GDB remote
    // server. But we might need a packet to detect this.
    return 0;
}

bool
PlatformRemoteGDBServer::GetRemoteOSVersion ()
{
    uint32_t major, minor, update;
    if (m_gdb_client.GetOSVersion (major, minor, update))
    {
        m_major_os_version = major;
        m_minor_os_version = minor;
        m_update_os_version = update;
        return true;
    }
    return false;
}

bool
PlatformRemoteGDBServer::GetRemoteOSBuildString (std::string &s)
{
    return m_gdb_client.GetOSBuildString (s);
}

bool
PlatformRemoteGDBServer::GetRemoteOSKernelDescription (std::string &s)
{
    return m_gdb_client.GetOSKernelDescription (s);
}

// Remote Platform subclasses need to override this function
ArchSpec
PlatformRemoteGDBServer::GetRemoteSystemArchitecture ()
{
    return m_gdb_client.GetSystemArchitecture();
}

FileSpec
PlatformRemoteGDBServer::GetRemoteWorkingDirectory()
{
    if (IsConnected())
    {
        Log *log = GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM);
        FileSpec working_dir;
        if (m_gdb_client.GetWorkingDir(working_dir) && log)
            log->Printf("PlatformRemoteGDBServer::GetRemoteWorkingDirectory() -> '%s'",
                    working_dir.GetCString());
        return working_dir;
    }
    else
    {
        return Platform::GetRemoteWorkingDirectory();
    }
}

bool
PlatformRemoteGDBServer::SetRemoteWorkingDirectory(const FileSpec &working_dir)
{
    if (IsConnected())
    {
        // Clear the working directory it case it doesn't get set correctly. This will
        // for use to re-read it
        Log *log = GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM);
        if (log)
            log->Printf("PlatformRemoteGDBServer::SetRemoteWorkingDirectory('%s')",
                    working_dir.GetCString());
        return m_gdb_client.SetWorkingDir(working_dir) == 0;
    }
    else
        return Platform::SetRemoteWorkingDirectory(working_dir);
}

bool
PlatformRemoteGDBServer::IsConnected () const
{
    return m_gdb_client.IsConnected();
}        

Error
PlatformRemoteGDBServer::ConnectRemote (Args& args)
{
    Error error;
    if (IsConnected())
    {
        error.SetErrorStringWithFormat ("the platform is already connected to '%s', execute 'platform disconnect' to close the current connection", 
                                        GetHostname());
    }
    else
    {
        if (args.GetArgumentCount() == 1)
        {
            m_gdb_client.SetConnection(new ConnectionFileDescriptor());
            // we're going to reuse the hostname when we connect to the debugserver
            int port;
            std::string path;
            const char *url = args.GetArgumentAtIndex(0);
            if (!url)
                return Error("URL is null.");
            if (!UriParser::Parse(url, m_platform_scheme, m_platform_hostname, port, path))
                return Error("Invalid URL: %s", url);

            const ConnectionStatus status = m_gdb_client.Connect(url, &error);
            if (status == eConnectionStatusSuccess)
            {
                if (m_gdb_client.HandshakeWithServer(&error))
                {
                    m_gdb_client.GetHostInfo();
                    // If a working directory was set prior to connecting, send it down now
                    if (m_working_dir)
                        m_gdb_client.SetWorkingDir(m_working_dir);
                }
                else
                {
                    m_gdb_client.Disconnect();
                    if (error.Success())
                        error.SetErrorString("handshake failed");
                }
            }
        }
        else
        {
            error.SetErrorString ("\"platform connect\" takes a single argument: <connect-url>");
        }
    }
    return error;
}

Error
PlatformRemoteGDBServer::DisconnectRemote ()
{
    Error error;
    m_gdb_client.Disconnect(&error);
    m_remote_signals_sp.reset();
    return error;
}

const char *
PlatformRemoteGDBServer::GetHostname ()
{
    m_gdb_client.GetHostname (m_name);
    if (m_name.empty())
        return NULL;
    return m_name.c_str();
}

const char *
PlatformRemoteGDBServer::GetUserName (uint32_t uid)
{
    // Try and get a cache user name first
    const char *cached_user_name = Platform::GetUserName(uid);
    if (cached_user_name)
        return cached_user_name;
    std::string name;
    if (m_gdb_client.GetUserName(uid, name))
        return SetCachedUserName(uid, name.c_str(), name.size());

    SetUserNameNotFound(uid); // Negative cache so we don't keep sending packets
    return NULL;
}

const char *
PlatformRemoteGDBServer::GetGroupName (uint32_t gid)
{
    const char *cached_group_name = Platform::GetGroupName(gid);
    if (cached_group_name)
        return cached_group_name;
    std::string name;
    if (m_gdb_client.GetGroupName(gid, name))
        return SetCachedGroupName(gid, name.c_str(), name.size());

    SetGroupNameNotFound(gid); // Negative cache so we don't keep sending packets
    return NULL;
}

uint32_t
PlatformRemoteGDBServer::FindProcesses (const ProcessInstanceInfoMatch &match_info,
                                        ProcessInstanceInfoList &process_infos)
{
    return m_gdb_client.FindProcesses (match_info, process_infos);
}

bool
PlatformRemoteGDBServer::GetProcessInfo (lldb::pid_t pid, ProcessInstanceInfo &process_info)
{
    return m_gdb_client.GetProcessInfo (pid, process_info);
}


Error
PlatformRemoteGDBServer::LaunchProcess (ProcessLaunchInfo &launch_info)
{
    Log *log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_PLATFORM));
    Error error;

    if (log)
        log->Printf ("PlatformRemoteGDBServer::%s() called", __FUNCTION__);

    auto num_file_actions = launch_info.GetNumFileActions ();
    for (decltype(num_file_actions) i = 0; i < num_file_actions; ++i)
    {
        const auto file_action = launch_info.GetFileActionAtIndex (i);
        if (file_action->GetAction () != FileAction::eFileActionOpen)
            continue;
        switch(file_action->GetFD())
        {
        case STDIN_FILENO:
            m_gdb_client.SetSTDIN(file_action->GetFileSpec());
            break;
        case STDOUT_FILENO:
            m_gdb_client.SetSTDOUT(file_action->GetFileSpec());
            break;
        case STDERR_FILENO:
            m_gdb_client.SetSTDERR(file_action->GetFileSpec());
            break;
        }
    }

    m_gdb_client.SetDisableASLR (launch_info.GetFlags().Test (eLaunchFlagDisableASLR));
    m_gdb_client.SetDetachOnError (launch_info.GetFlags().Test (eLaunchFlagDetachOnError));
    
    FileSpec working_dir = launch_info.GetWorkingDirectory();
    if (working_dir)
    {
        m_gdb_client.SetWorkingDir(working_dir);
    }
    
    // Send the environment and the program + arguments after we connect
    const char **envp = launch_info.GetEnvironmentEntries().GetConstArgumentVector();

    if (envp)
    {
        const char *env_entry;
        for (int i=0; (env_entry = envp[i]); ++i)
        {
            if (m_gdb_client.SendEnvironmentPacket(env_entry) != 0)
                break;
        }
    }
    
    ArchSpec arch_spec = launch_info.GetArchitecture();
    const char *arch_triple = arch_spec.GetTriple().str().c_str();
    
    m_gdb_client.SendLaunchArchPacket(arch_triple);
    if (log)
        log->Printf ("PlatformRemoteGDBServer::%s() set launch architecture triple to '%s'", __FUNCTION__, arch_triple ? arch_triple : "<NULL>");

    int arg_packet_err;
    {
        // Scope for the scoped timeout object
        process_gdb_remote::GDBRemoteCommunication::ScopedTimeout timeout(m_gdb_client, 5);
        arg_packet_err = m_gdb_client.SendArgumentsPacket (launch_info);
    }

    if (arg_packet_err == 0)
    {
        std::string error_str;
        if (m_gdb_client.GetLaunchSuccess (error_str))
        {
            const auto pid = m_gdb_client.GetCurrentProcessID (false);
            if (pid != LLDB_INVALID_PROCESS_ID)
            {
                launch_info.SetProcessID (pid);
                if (log)
                    log->Printf ("PlatformRemoteGDBServer::%s() pid %" PRIu64 " launched successfully", __FUNCTION__, pid);
            }
            else
            {
                if (log)
                    log->Printf ("PlatformRemoteGDBServer::%s() launch succeeded but we didn't get a valid process id back!", __FUNCTION__);
                error.SetErrorString ("failed to get PID");
            }
        }
        else
        {
            error.SetErrorString (error_str.c_str());
            if (log)
                log->Printf ("PlatformRemoteGDBServer::%s() launch failed: %s", __FUNCTION__, error.AsCString ());
        }
    }
    else
    {
        error.SetErrorStringWithFormat("'A' packet returned an error: %i", arg_packet_err);
    }
    return error;
}

Error
PlatformRemoteGDBServer::KillProcess (const lldb::pid_t pid)
{
    if (!KillSpawnedProcess(pid))
        return Error("failed to kill remote spawned process");
    return Error();
}

lldb::ProcessSP
PlatformRemoteGDBServer::DebugProcess (ProcessLaunchInfo &launch_info,
                                       Debugger &debugger,
                                       Target *target,       // Can be NULL, if NULL create a new target, else use existing one
                                       Error &error)
{
    lldb::ProcessSP process_sp;
    if (IsRemote())
    {
        if (IsConnected())
        {
            lldb::pid_t debugserver_pid = LLDB_INVALID_PROCESS_ID;
            std::string connect_url;
            if (!LaunchGDBServer(debugserver_pid, connect_url))
            {
                error.SetErrorStringWithFormat ("unable to launch a GDB server on '%s'", GetHostname ());
            }
            else
            {
                if (target == NULL)
                {
                    TargetSP new_target_sp;
                    
                    error = debugger.GetTargetList().CreateTarget (debugger,
                                                                   NULL,
                                                                   NULL,
                                                                   false,
                                                                   NULL,
                                                                   new_target_sp);
                    target = new_target_sp.get();
                }
                else
                    error.Clear();
                
                if (target && error.Success())
                {
                    debugger.GetTargetList().SetSelectedTarget(target);
                    
                    // The darwin always currently uses the GDB remote debugger plug-in
                    // so even when debugging locally we are debugging remotely!
                    process_sp = target->CreateProcess (launch_info.GetListenerForProcess(debugger), "gdb-remote", NULL);
                    
                    if (process_sp)
                    {
                        error = process_sp->ConnectRemote (nullptr, connect_url.c_str());
                        // Retry the connect remote one time...
                        if (error.Fail())
                            error = process_sp->ConnectRemote (nullptr, connect_url.c_str());
                        if (error.Success())
                            error = process_sp->Launch(launch_info);
                        else if (debugserver_pid != LLDB_INVALID_PROCESS_ID)
                        {
                            printf ("error: connect remote failed (%s)\n", error.AsCString());
                            KillSpawnedProcess(debugserver_pid);
                        }
                    }
                }
            }
        }
        else
        {
            error.SetErrorString("not connected to remote gdb server");
        }
    }
    return process_sp;

}

bool
PlatformRemoteGDBServer::LaunchGDBServer (lldb::pid_t &pid, std::string &connect_url)
{
    ArchSpec remote_arch = GetRemoteSystemArchitecture ();
    llvm::Triple &remote_triple = remote_arch.GetTriple ();

    uint16_t port = 0;
    std::string socket_name;
    bool launch_result = false;
    if (remote_triple.getVendor () == llvm::Triple::Apple && remote_triple.getOS () == llvm::Triple::IOS)
    {
        // When remote debugging to iOS, we use a USB mux that always talks
        // to localhost, so we will need the remote debugserver to accept connections
        // only from localhost, no matter what our current hostname is
        launch_result = m_gdb_client.LaunchGDBServer ("127.0.0.1", pid, port, socket_name);
    }
    else
    {
        // All other hosts should use their actual hostname
        launch_result = m_gdb_client.LaunchGDBServer (nullptr, pid, port, socket_name);
    }

    if (!launch_result)
        return false;

    connect_url = MakeGdbServerUrl(m_platform_scheme,
                                   m_platform_hostname,
                                   port,
                                   (socket_name.empty()) ? nullptr : socket_name.c_str());
    return true;
}

bool
PlatformRemoteGDBServer::KillSpawnedProcess (lldb::pid_t pid)
{
    return m_gdb_client.KillSpawnedProcess (pid);
}

lldb::ProcessSP
PlatformRemoteGDBServer::Attach (ProcessAttachInfo &attach_info,
                                 Debugger &debugger,
                                 Target *target,       // Can be NULL, if NULL create a new target, else use existing one
                                 Error &error)
{
    lldb::ProcessSP process_sp;
    if (IsRemote())
    {
        if (IsConnected())
        {
            lldb::pid_t debugserver_pid = LLDB_INVALID_PROCESS_ID;
            std::string connect_url;
            if (!LaunchGDBServer(debugserver_pid, connect_url))
            {
                error.SetErrorStringWithFormat ("unable to launch a GDB server on '%s'", GetHostname ());
            }
            else
            {
                if (target == NULL)
                {
                    TargetSP new_target_sp;
                    
                    error = debugger.GetTargetList().CreateTarget (debugger,
                                                                   NULL,
                                                                   NULL, 
                                                                   false,
                                                                   NULL,
                                                                   new_target_sp);
                    target = new_target_sp.get();
                }
                else
                    error.Clear();
                
                if (target && error.Success())
                {
                    debugger.GetTargetList().SetSelectedTarget(target);
                    
                    // The darwin always currently uses the GDB remote debugger plug-in
                    // so even when debugging locally we are debugging remotely!
                    process_sp = target->CreateProcess (attach_info.GetListenerForProcess(debugger), "gdb-remote", NULL);
                    if (process_sp)
                    {
                        error = process_sp->ConnectRemote(nullptr, connect_url.c_str());
                        if (error.Success())
                        {
                            auto listener = attach_info.GetHijackListener();
                            if (listener != nullptr)
                                process_sp->HijackProcessEvents(listener.get());
                            error = process_sp->Attach(attach_info);
                        }

                        if (error.Fail() && debugserver_pid != LLDB_INVALID_PROCESS_ID)
                        {
                            KillSpawnedProcess(debugserver_pid);
                        }
                    }
                }
            }
        }
        else
        {
            error.SetErrorString("not connected to remote gdb server");
        }
    }
    return process_sp;
}

Error
PlatformRemoteGDBServer::MakeDirectory(const FileSpec &file_spec, uint32_t mode)
{
    Error error = m_gdb_client.MakeDirectory(file_spec, mode);
    Log *log = GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM);
    if (log)
        log->Printf ("PlatformRemoteGDBServer::MakeDirectory(path='%s', mode=%o) error = %u (%s)",
                file_spec.GetCString(), mode, error.GetError(), error.AsCString());
    return error;
}


Error
PlatformRemoteGDBServer::GetFilePermissions(const FileSpec &file_spec,
                                            uint32_t &file_permissions)
{
    Error error = m_gdb_client.GetFilePermissions(file_spec, file_permissions);
    Log *log = GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM);
    if (log)
        log->Printf ("PlatformRemoteGDBServer::GetFilePermissions(path='%s', file_permissions=%o) error = %u (%s)",
                file_spec.GetCString(), file_permissions, error.GetError(), error.AsCString());
    return error;
}

Error
PlatformRemoteGDBServer::SetFilePermissions(const FileSpec &file_spec,
                                            uint32_t file_permissions)
{
    Error error = m_gdb_client.SetFilePermissions(file_spec, file_permissions);
    Log *log = GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM);
    if (log)
        log->Printf ("PlatformRemoteGDBServer::SetFilePermissions(path='%s', file_permissions=%o) error = %u (%s)",
                file_spec.GetCString(), file_permissions, error.GetError(), error.AsCString());
    return error;
}


lldb::user_id_t
PlatformRemoteGDBServer::OpenFile (const FileSpec& file_spec,
                                   uint32_t flags,
                                   uint32_t mode,
                                   Error &error)
{
    return m_gdb_client.OpenFile (file_spec, flags, mode, error);
}

bool
PlatformRemoteGDBServer::CloseFile (lldb::user_id_t fd, Error &error)
{
    return m_gdb_client.CloseFile (fd, error);
}

lldb::user_id_t
PlatformRemoteGDBServer::GetFileSize (const FileSpec& file_spec)
{
    return m_gdb_client.GetFileSize(file_spec);
}

uint64_t
PlatformRemoteGDBServer::ReadFile (lldb::user_id_t fd,
                                   uint64_t offset,
                                   void *dst,
                                   uint64_t dst_len,
                                   Error &error)
{
    return m_gdb_client.ReadFile (fd, offset, dst, dst_len, error);
}

uint64_t
PlatformRemoteGDBServer::WriteFile (lldb::user_id_t fd,
                                    uint64_t offset,
                                    const void* src,
                                    uint64_t src_len,
                                    Error &error)
{
    return m_gdb_client.WriteFile (fd, offset, src, src_len, error);
}

Error
PlatformRemoteGDBServer::PutFile (const FileSpec& source,
         const FileSpec& destination,
         uint32_t uid,
         uint32_t gid)
{
    return Platform::PutFile(source,destination,uid,gid);
}

Error
PlatformRemoteGDBServer::CreateSymlink(const FileSpec &src,    // The name of the link is in src
                                       const FileSpec &dst)    // The symlink points to dst
{
    Error error = m_gdb_client.CreateSymlink(src, dst);
    Log *log = GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM);
    if (log)
        log->Printf ("PlatformRemoteGDBServer::CreateSymlink(src='%s', dst='%s') error = %u (%s)",
                src.GetCString(), dst.GetCString(), error.GetError(), error.AsCString());
    return error;
}

Error
PlatformRemoteGDBServer::Unlink(const FileSpec &file_spec)
{
    Error error = m_gdb_client.Unlink(file_spec);
    Log *log = GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM);
    if (log)
        log->Printf ("PlatformRemoteGDBServer::Unlink(path='%s') error = %u (%s)",
                file_spec.GetCString(), error.GetError(), error.AsCString());
    return error;
}

bool
PlatformRemoteGDBServer::GetFileExists (const FileSpec& file_spec)
{
    return m_gdb_client.GetFileExists (file_spec);
}

Error
PlatformRemoteGDBServer::RunShellCommand(const char *command,           // Shouldn't be NULL
                                         const FileSpec &working_dir,   // Pass empty FileSpec to use the current working directory
                                         int *status_ptr,               // Pass NULL if you don't want the process exit status
                                         int *signo_ptr,                // Pass NULL if you don't want the signal that caused the process to exit
                                         std::string *command_output,   // Pass NULL if you don't want the command output
                                         uint32_t timeout_sec)          // Timeout in seconds to wait for shell program to finish
{
    return m_gdb_client.RunShellCommand(command, working_dir, status_ptr, signo_ptr, command_output, timeout_sec);
}

void
PlatformRemoteGDBServer::CalculateTrapHandlerSymbolNames ()
{
    m_trap_handlers.push_back (ConstString ("_sigtramp"));
}

const UnixSignalsSP &
PlatformRemoteGDBServer::GetRemoteUnixSignals()
{
    if (!IsConnected())
        return Platform::GetRemoteUnixSignals();

    if (m_remote_signals_sp)
        return m_remote_signals_sp;

    // If packet not implemented or JSON failed to parse,
    // we'll guess the signal set based on the remote architecture.
    m_remote_signals_sp = UnixSignals::Create(GetRemoteSystemArchitecture());

    const char packet[] = "jSignalsInfo";
    StringExtractorGDBRemote response;
    auto result = m_gdb_client.SendPacketAndWaitForResponse(
            packet, strlen(packet), response, false);

    if (result != decltype(result)::Success ||
            response.GetResponseType() != response.eResponse)
        return m_remote_signals_sp;

    auto object_sp = StructuredData::ParseJSON(response.GetStringRef());
    if (!object_sp || !object_sp->IsValid())
        return m_remote_signals_sp;

    auto array_sp = object_sp->GetAsArray();
    if (!array_sp || !array_sp->IsValid())
        return m_remote_signals_sp;

    auto remote_signals_sp = std::make_shared<lldb_private::GDBRemoteSignals>();

    bool done = array_sp->ForEach(
        [&remote_signals_sp](StructuredData::Object *object) -> bool
        {
            if (!object || !object->IsValid())
                return false;

            auto dict = object->GetAsDictionary();
            if (!dict || !dict->IsValid())
                return false;

            // Signal number and signal name are required.
            int signo;
            if (!dict->GetValueForKeyAsInteger("signo", signo))
                return false;

            std::string name;
            if (!dict->GetValueForKeyAsString("name", name))
                return false;

            // We can live without short_name, description, etc.
            bool suppress{false};
            auto object_sp = dict->GetValueForKey("suppress");
            if (object_sp && object_sp->IsValid())
                suppress = object_sp->GetBooleanValue();

            bool stop{false};
            object_sp = dict->GetValueForKey("stop");
            if (object_sp && object_sp->IsValid())
                stop = object_sp->GetBooleanValue();

            bool notify{false};
            object_sp = dict->GetValueForKey("notify");
            if (object_sp && object_sp->IsValid())
                notify = object_sp->GetBooleanValue();

            std::string description{""};
            object_sp = dict->GetValueForKey("description");
            if (object_sp && object_sp->IsValid())
                description = object_sp->GetStringValue();

            remote_signals_sp->AddSignal(signo,
                                         name.c_str(),
                                         suppress, stop, notify,
                                         description.c_str());
            return true;
        });

    if (done)
        m_remote_signals_sp = std::move(remote_signals_sp);

    return m_remote_signals_sp;
}

std::string
PlatformRemoteGDBServer::MakeGdbServerUrl(const std::string &platform_scheme,
                                          const std::string &platform_hostname,
                                          uint16_t port,
                                          const char* socket_name)
{
    const char *override_scheme = getenv("LLDB_PLATFORM_REMOTE_GDB_SERVER_SCHEME");
    const char *override_hostname = getenv("LLDB_PLATFORM_REMOTE_GDB_SERVER_HOSTNAME");
    const char *port_offset_c_str = getenv("LLDB_PLATFORM_REMOTE_GDB_SERVER_PORT_OFFSET");
    int port_offset = port_offset_c_str ? ::atoi(port_offset_c_str) : 0;

    return MakeUrl(override_scheme ? override_scheme : platform_scheme.c_str(),
                   override_hostname ? override_hostname : platform_hostname.c_str(),
                   port + port_offset,
                   socket_name);
}

std::string
PlatformRemoteGDBServer::MakeUrl(const char* scheme,
                                 const char* hostname,
                                 uint16_t port,
                                 const char* path)
{
    StreamString result;
    result.Printf("%s://%s", scheme, hostname);
    if (port != 0)
        result.Printf(":%u", port);
    if (path)
        result.Write(path, strlen(path));
    return result.GetString();
}

lldb::ProcessSP
PlatformRemoteGDBServer::ConnectProcess(const char* connect_url,
                                        const char* plugin_name,
                                        lldb_private::Debugger &debugger,
                                        lldb_private::Target *target,
                                        lldb_private::Error &error)
{
    if (!IsRemote() || !IsConnected())
    {
        error.SetErrorString("Not connected to remote gdb server");
        return nullptr;
    }
    return Platform::ConnectProcess(connect_url, plugin_name, debugger, target, error);
}

size_t
PlatformRemoteGDBServer::ConnectToWaitingProcesses(Debugger& debugger, Error& error)
{
    std::vector<std::string> connection_urls;
    GetPendingGdbServerList(connection_urls);

    for (size_t i = 0; i < connection_urls.size(); ++i)
    {
        ConnectProcess(connection_urls[i].c_str(), nullptr, debugger, nullptr, error);
        if (error.Fail())
            return i; // We already connected to i process succsessfully
    }
    return connection_urls.size();

}

size_t
PlatformRemoteGDBServer::GetPendingGdbServerList(std::vector<std::string>& connection_urls)
{
    std::vector<std::pair<uint16_t, std::string>> remote_servers;
    m_gdb_client.QueryGDBServer(remote_servers);
    for (const auto& gdbserver : remote_servers)
    {
        const char* socket_name_cstr = gdbserver.second.empty() ? nullptr : gdbserver.second.c_str();
        connection_urls.emplace_back(MakeGdbServerUrl(m_platform_scheme,
                                                      m_platform_hostname,
                                                      gdbserver.first,
                                                      socket_name_cstr));
    }
    return connection_urls.size();
}
