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

// C Includes
#include <errno.h>
#include <stdlib.h>

// C++ Includes
#include <mutex>

// Other libraries and framework includes
#include "lldb/Core/Debugger.h"
#include "lldb/Core/PluginManager.h"
#include "lldb/Core/Module.h"
#include "lldb/Core/ModuleSpec.h"
#include "lldb/Core/State.h"
#include "lldb/Core/UUID.h"
#include "lldb/Host/ConnectionFileDescriptor.h"
#include "lldb/Host/Host.h"
#include "lldb/Host/Symbols.h"
#include "lldb/Host/ThreadLauncher.h"
#include "lldb/Host/common/TCPSocket.h"
#include "lldb/Interpreter/CommandInterpreter.h"
#include "lldb/Interpreter/CommandObject.h"
#include "lldb/Interpreter/CommandObjectMultiword.h"
#include "lldb/Interpreter/CommandReturnObject.h"
#include "lldb/Interpreter/OptionGroupString.h"
#include "lldb/Interpreter/OptionGroupUInt64.h"
#include "lldb/Interpreter/OptionValueProperties.h"
#include "lldb/Symbol/ObjectFile.h"
#include "lldb/Target/RegisterContext.h"
#include "lldb/Target/Target.h"
#include "lldb/Target/Thread.h"
#include "lldb/Utility/StringExtractor.h"

#define USEC_PER_SEC 1000000

// Project includes
#include "ProcessKDP.h"
#include "ProcessKDPLog.h"
#include "ThreadKDP.h"
#include "Plugins/DynamicLoader/Darwin-Kernel/DynamicLoaderDarwinKernel.h"
#include "Plugins/DynamicLoader/Static/DynamicLoaderStatic.h"

using namespace lldb;
using namespace lldb_private;

namespace {

    static PropertyDefinition
    g_properties[] =
    {
        { "packet-timeout" , OptionValue::eTypeUInt64 , true , 5, NULL, NULL, "Specify the default packet timeout in seconds." },
        {  NULL            , OptionValue::eTypeInvalid, false, 0, NULL, NULL, NULL  }
    };
    
    enum
    {
        ePropertyPacketTimeout
    };

    class PluginProperties : public Properties
    {
    public:
        
        static ConstString
        GetSettingName ()
        {
            return ProcessKDP::GetPluginNameStatic();
        }

        PluginProperties() :
            Properties ()
        {
            m_collection_sp.reset (new OptionValueProperties(GetSettingName()));
            m_collection_sp->Initialize(g_properties);
        }
        
        virtual
        ~PluginProperties()
        {
        }
        
        uint64_t
        GetPacketTimeout()
        {
            const uint32_t idx = ePropertyPacketTimeout;
            return m_collection_sp->GetPropertyAtIndexAsUInt64(NULL, idx, g_properties[idx].default_uint_value);
        }
    };

    typedef std::shared_ptr<PluginProperties> ProcessKDPPropertiesSP;

    static const ProcessKDPPropertiesSP &
    GetGlobalPluginProperties()
    {
        static ProcessKDPPropertiesSP g_settings_sp;
        if (!g_settings_sp)
            g_settings_sp.reset (new PluginProperties ());
        return g_settings_sp;
    }
    
} // anonymous namespace end

static const lldb::tid_t g_kernel_tid = 1;

ConstString
ProcessKDP::GetPluginNameStatic()
{
    static ConstString g_name("kdp-remote");
    return g_name;
}

const char *
ProcessKDP::GetPluginDescriptionStatic()
{
    return "KDP Remote protocol based debugging plug-in for darwin kernel debugging.";
}

void
ProcessKDP::Terminate()
{
    PluginManager::UnregisterPlugin (ProcessKDP::CreateInstance);
}


lldb::ProcessSP
ProcessKDP::CreateInstance (TargetSP target_sp,
                            ListenerSP listener_sp,
                            const FileSpec *crash_file_path)
{
    lldb::ProcessSP process_sp;
    if (crash_file_path == NULL)
        process_sp.reset(new ProcessKDP (target_sp, listener_sp));
    return process_sp;
}

bool
ProcessKDP::CanDebug(TargetSP target_sp, bool plugin_specified_by_name)
{
    if (plugin_specified_by_name)
        return true;

    // For now we are just making sure the file exists for a given module
    Module *exe_module = target_sp->GetExecutableModulePointer();
    if (exe_module)
    {
        const llvm::Triple &triple_ref = target_sp->GetArchitecture().GetTriple();
        switch (triple_ref.getOS())
        {
            case llvm::Triple::Darwin:  // Should use "macosx" for desktop and "ios" for iOS, but accept darwin just in case
            case llvm::Triple::MacOSX:  // For desktop targets
            case llvm::Triple::IOS:     // For arm targets
            case llvm::Triple::TvOS:
            case llvm::Triple::WatchOS:
                if (triple_ref.getVendor() == llvm::Triple::Apple)
                {
                    ObjectFile *exe_objfile = exe_module->GetObjectFile();
                    if (exe_objfile->GetType() == ObjectFile::eTypeExecutable && 
                        exe_objfile->GetStrata() == ObjectFile::eStrataKernel)
                        return true;
                }
                break;

            default:
                break;
        }
    }
    return false;
}

//----------------------------------------------------------------------
// ProcessKDP constructor
//----------------------------------------------------------------------
ProcessKDP::ProcessKDP(TargetSP target_sp, ListenerSP listener_sp) :
    Process (target_sp, listener_sp),
    m_comm("lldb.process.kdp-remote.communication"),
    m_async_broadcaster (NULL, "lldb.process.kdp-remote.async-broadcaster"),
    m_dyld_plugin_name (),
    m_kernel_load_addr (LLDB_INVALID_ADDRESS),
    m_command_sp(),
    m_kernel_thread_wp()
{
    m_async_broadcaster.SetEventName (eBroadcastBitAsyncThreadShouldExit,   "async thread should exit");
    m_async_broadcaster.SetEventName (eBroadcastBitAsyncContinue,           "async thread continue");
    const uint64_t timeout_seconds = GetGlobalPluginProperties()->GetPacketTimeout();
    if (timeout_seconds > 0)
        m_comm.SetPacketTimeout(timeout_seconds);
}

//----------------------------------------------------------------------
// Destructor
//----------------------------------------------------------------------
ProcessKDP::~ProcessKDP()
{
    Clear();
    // We need to call finalize on the process before destroying ourselves
    // to make sure all of the broadcaster cleanup goes as planned. If we
    // destruct this class, then Process::~Process() might have problems
    // trying to fully destroy the broadcaster.
    Finalize();
}

//----------------------------------------------------------------------
// PluginInterface
//----------------------------------------------------------------------
lldb_private::ConstString
ProcessKDP::GetPluginName()
{
    return GetPluginNameStatic();
}

uint32_t
ProcessKDP::GetPluginVersion()
{
    return 1;
}

Error
ProcessKDP::WillLaunch (Module* module)
{
    Error error;
    error.SetErrorString ("launching not supported in kdp-remote plug-in");
    return error;
}

Error
ProcessKDP::WillAttachToProcessWithID (lldb::pid_t pid)
{
    Error error;
    error.SetErrorString ("attaching to a by process ID not supported in kdp-remote plug-in");
    return error;
}

Error
ProcessKDP::WillAttachToProcessWithName (const char *process_name, bool wait_for_launch)
{
    Error error;
    error.SetErrorString ("attaching to a by process name not supported in kdp-remote plug-in");
    return error;
}

bool
ProcessKDP::GetHostArchitecture(ArchSpec &arch)
{
    uint32_t cpu = m_comm.GetCPUType();
    if (cpu)
    {
        uint32_t sub = m_comm.GetCPUSubtype();
        arch.SetArchitecture(eArchTypeMachO, cpu, sub);
        // Leave architecture vendor as unspecified unknown
        arch.GetTriple().setVendor(llvm::Triple::UnknownVendor);
        arch.GetTriple().setVendorName(llvm::StringRef());
        return true;
    }
    arch.Clear();
    return false;
}

Error
ProcessKDP::DoConnectRemote (Stream *strm, const char *remote_url)
{
    Error error;

    // Don't let any JIT happen when doing KDP as we can't allocate
    // memory and we don't want to be mucking with threads that might
    // already be handling exceptions
    SetCanJIT(false);

    if (remote_url == NULL || remote_url[0] == '\0')
    {
        error.SetErrorStringWithFormat ("invalid connection URL '%s'", remote_url);
        return error;
    }

    std::unique_ptr<ConnectionFileDescriptor> conn_ap(new ConnectionFileDescriptor());
    if (conn_ap.get())
    {
        // Only try once for now.
        // TODO: check if we should be retrying?
        const uint32_t max_retry_count = 1;
        for (uint32_t retry_count = 0; retry_count < max_retry_count; ++retry_count)
        {
            if (conn_ap->Connect(remote_url, &error) == eConnectionStatusSuccess)
                break;
            usleep (100000);
        }
    }

    if (conn_ap->IsConnected())
    {
        const TCPSocket& socket = static_cast<const TCPSocket&>(*conn_ap->GetReadObject());
        const uint16_t reply_port = socket.GetLocalPortNumber();

        if (reply_port != 0)
        {
            m_comm.SetConnection(conn_ap.release());

            if (m_comm.SendRequestReattach(reply_port))
            {
                if (m_comm.SendRequestConnect(reply_port, reply_port, "Greetings from LLDB..."))
                {
                    m_comm.GetVersion();

                    Target &target = GetTarget();
                    ArchSpec kernel_arch;
                    // The host architecture
                    GetHostArchitecture(kernel_arch);
                    ArchSpec target_arch = target.GetArchitecture();
                    // Merge in any unspecified stuff into the target architecture in
                    // case the target arch isn't set at all or incompletely.
                    target_arch.MergeFrom(kernel_arch);
                    target.SetArchitecture(target_arch);

                    /* Get the kernel's UUID and load address via KDP_KERNELVERSION packet.  */
                    /* An EFI kdp session has neither UUID nor load address. */

                    UUID kernel_uuid = m_comm.GetUUID ();
                    addr_t kernel_load_addr = m_comm.GetLoadAddress ();

                    if (m_comm.RemoteIsEFI ())
                    {
                        // Select an invalid plugin name for the dynamic loader so one doesn't get used
                        // since EFI does its own manual loading via python scripting
                        static ConstString g_none_dynamic_loader("none");
                        m_dyld_plugin_name = g_none_dynamic_loader;

                        if (kernel_uuid.IsValid()) {
                            // If EFI passed in a UUID= try to lookup UUID
                            // The slide will not be provided. But the UUID
                            // lookup will be used to launch EFI debug scripts
                            // from the dSYM, that can load all of the symbols.
                            ModuleSpec module_spec;
                            module_spec.GetUUID() = kernel_uuid;
                            module_spec.GetArchitecture() = target.GetArchitecture();

                            // Lookup UUID locally, before attempting dsymForUUID like action
                            module_spec.GetSymbolFileSpec() = Symbols::LocateExecutableSymbolFile(module_spec);
                            if (module_spec.GetSymbolFileSpec())
                            {
                                ModuleSpec executable_module_spec = Symbols::LocateExecutableObjectFile (module_spec);
                                if (executable_module_spec.GetFileSpec().Exists())
                                {
                                    module_spec.GetFileSpec() = executable_module_spec.GetFileSpec();
                                }
                            }
                            if (!module_spec.GetSymbolFileSpec() || !module_spec.GetSymbolFileSpec())
                                 Symbols::DownloadObjectAndSymbolFile (module_spec, true);

                            if (module_spec.GetFileSpec().Exists())
                            {
                                ModuleSP module_sp(new Module (module_spec));
                                if (module_sp.get() && module_sp->GetObjectFile())
                                {
                                    // Get the current target executable
                                    ModuleSP exe_module_sp (target.GetExecutableModule ());

                                    // Make sure you don't already have the right module loaded and they will be uniqued
                                    if (exe_module_sp.get() != module_sp.get())
                                        target.SetExecutableModule (module_sp, false);
                                }
                            }
                        }
                    }
                    else if (m_comm.RemoteIsDarwinKernel ())
                    {
                        m_dyld_plugin_name = DynamicLoaderDarwinKernel::GetPluginNameStatic();
                        if (kernel_load_addr != LLDB_INVALID_ADDRESS)
                        {
                            m_kernel_load_addr = kernel_load_addr;
                        }
                    }

                    // Set the thread ID
                    UpdateThreadListIfNeeded ();
                    SetID (1);
                    GetThreadList ();
                    SetPrivateState (eStateStopped);
                    StreamSP async_strm_sp(target.GetDebugger().GetAsyncOutputStream());
                    if (async_strm_sp)
                    {
                        const char *cstr;
                        if ((cstr = m_comm.GetKernelVersion ()) != NULL)
                        {
                            async_strm_sp->Printf ("Version: %s\n", cstr);
                            async_strm_sp->Flush();
                        }
//                      if ((cstr = m_comm.GetImagePath ()) != NULL)
//                      {
//                          async_strm_sp->Printf ("Image Path: %s\n", cstr);
//                          async_strm_sp->Flush();
//                      }            
                    }
                }
                else
                {
                    error.SetErrorString("KDP_REATTACH failed");
                }
            }
            else
            {
                error.SetErrorString("KDP_REATTACH failed");
            }
        }
        else
        {
            error.SetErrorString("invalid reply port from UDP connection");
        }
    }
    else
    {
        if (error.Success())
            error.SetErrorStringWithFormat ("failed to connect to '%s'", remote_url);
    }
    if (error.Fail())
        m_comm.Disconnect();

    return error;
}

//----------------------------------------------------------------------
// Process Control
//----------------------------------------------------------------------
Error
ProcessKDP::DoLaunch (Module *exe_module, 
                      ProcessLaunchInfo &launch_info)
{
    Error error;
    error.SetErrorString ("launching not supported in kdp-remote plug-in");
    return error;
}

Error
ProcessKDP::DoAttachToProcessWithID (lldb::pid_t attach_pid, const ProcessAttachInfo &attach_info)
{
    Error error;
    error.SetErrorString ("attach to process by ID is not suppported in kdp remote debugging");
    return error;
}

Error
ProcessKDP::DoAttachToProcessWithName (const char *process_name, const ProcessAttachInfo &attach_info)
{
    Error error;
    error.SetErrorString ("attach to process by name is not suppported in kdp remote debugging");
    return error;
}


void
ProcessKDP::DidAttach (ArchSpec &process_arch)
{
    Process::DidAttach(process_arch);
    
    Log *log (ProcessKDPLog::GetLogIfAllCategoriesSet (KDP_LOG_PROCESS));
    if (log)
        log->Printf ("ProcessKDP::DidAttach()");
    if (GetID() != LLDB_INVALID_PROCESS_ID)
    {
        GetHostArchitecture(process_arch);
    }
}

addr_t
ProcessKDP::GetImageInfoAddress()
{
    return m_kernel_load_addr;
}

lldb_private::DynamicLoader *
ProcessKDP::GetDynamicLoader ()
{
    if (m_dyld_ap.get() == NULL)
        m_dyld_ap.reset (DynamicLoader::FindPlugin(this, m_dyld_plugin_name.IsEmpty() ? NULL : m_dyld_plugin_name.GetCString()));
    return m_dyld_ap.get();
}

Error
ProcessKDP::WillResume ()
{
    return Error();
}

Error
ProcessKDP::DoResume ()
{
    Error error;
    Log *log (ProcessKDPLog::GetLogIfAllCategoriesSet (KDP_LOG_PROCESS));
    // Only start the async thread if we try to do any process control
    if (!m_async_thread.IsJoinable())
        StartAsyncThread();

    bool resume = false;
    
    // With KDP there is only one thread we can tell what to do
    ThreadSP kernel_thread_sp (m_thread_list.FindThreadByProtocolID(g_kernel_tid));
                            
    if (kernel_thread_sp)
    {
        const StateType thread_resume_state = kernel_thread_sp->GetTemporaryResumeState();
        
        if (log)
            log->Printf ("ProcessKDP::DoResume() thread_resume_state = %s", StateAsCString(thread_resume_state));
        switch (thread_resume_state)
        {
            case eStateSuspended:
                // Nothing to do here when a thread will stay suspended
                // we just leave the CPU mask bit set to zero for the thread
                if (log)
                    log->Printf ("ProcessKDP::DoResume() = suspended???");
                break;
                
            case eStateStepping:
                {
                    lldb::RegisterContextSP reg_ctx_sp (kernel_thread_sp->GetRegisterContext());

                    if (reg_ctx_sp)
                    {
                        if (log)
                            log->Printf ("ProcessKDP::DoResume () reg_ctx_sp->HardwareSingleStep (true);");
                        reg_ctx_sp->HardwareSingleStep (true);
                        resume = true;
                    }
                    else
                    {
                        error.SetErrorStringWithFormat("KDP thread 0x%llx has no register context", kernel_thread_sp->GetID());
                    }
                }
                break;
    
            case eStateRunning:
                {
                    lldb::RegisterContextSP reg_ctx_sp (kernel_thread_sp->GetRegisterContext());
                    
                    if (reg_ctx_sp)
                    {
                        if (log)
                            log->Printf ("ProcessKDP::DoResume () reg_ctx_sp->HardwareSingleStep (false);");
                        reg_ctx_sp->HardwareSingleStep (false);
                        resume = true;
                    }
                    else
                    {
                        error.SetErrorStringWithFormat("KDP thread 0x%llx has no register context", kernel_thread_sp->GetID());
                    }
                }
                break;

            default:
                // The only valid thread resume states are listed above
                assert (!"invalid thread resume state");
                break;
        }
    }

    if (resume)
    {
        if (log)
            log->Printf ("ProcessKDP::DoResume () sending resume");
        
        if (m_comm.SendRequestResume ())
        {
            m_async_broadcaster.BroadcastEvent (eBroadcastBitAsyncContinue);
            SetPrivateState(eStateRunning);
        }
        else
            error.SetErrorString ("KDP resume failed");
    }
    else
    {
        error.SetErrorString ("kernel thread is suspended");        
    }
    
    return error;
}

lldb::ThreadSP
ProcessKDP::GetKernelThread()
{
    // KDP only tells us about one thread/core. Any other threads will usually
    // be the ones that are read from memory by the OS plug-ins.
    
    ThreadSP thread_sp (m_kernel_thread_wp.lock());
    if (!thread_sp)
    {
        thread_sp.reset(new ThreadKDP (*this, g_kernel_tid));
        m_kernel_thread_wp = thread_sp;
    }
    return thread_sp;
}




bool
ProcessKDP::UpdateThreadList (ThreadList &old_thread_list, ThreadList &new_thread_list)
{
    // locker will keep a mutex locked until it goes out of scope
    Log *log (ProcessKDPLog::GetLogIfAllCategoriesSet (KDP_LOG_THREAD));
    if (log && log->GetMask().Test(KDP_LOG_VERBOSE))
        log->Printf ("ProcessKDP::%s (pid = %" PRIu64 ")", __FUNCTION__, GetID());
    
    // Even though there is a CPU mask, it doesn't mean we can see each CPU
    // individually, there is really only one. Lets call this thread 1.
    ThreadSP thread_sp (old_thread_list.FindThreadByProtocolID(g_kernel_tid, false));
    if (!thread_sp)
        thread_sp = GetKernelThread ();
    new_thread_list.AddThread(thread_sp);

    return new_thread_list.GetSize(false) > 0;
}

void
ProcessKDP::RefreshStateAfterStop ()
{
    // Let all threads recover from stopping and do any clean up based
    // on the previous thread state (if any).
    m_thread_list.RefreshStateAfterStop();
}

Error
ProcessKDP::DoHalt (bool &caused_stop)
{
    Error error;
    
    if (m_comm.IsRunning())
    {
        if (m_destroy_in_process)
        {
            // If we are attemping to destroy, we need to not return an error to
            // Halt or DoDestroy won't get called.
            // We are also currently running, so send a process stopped event
            SetPrivateState (eStateStopped);
        }
        else
        {
            error.SetErrorString ("KDP cannot interrupt a running kernel");
        }
    }
    return error;
}

Error
ProcessKDP::DoDetach(bool keep_stopped)
{
    Error error;
    Log *log (ProcessKDPLog::GetLogIfAllCategoriesSet(KDP_LOG_PROCESS));
    if (log)
        log->Printf ("ProcessKDP::DoDetach(keep_stopped = %i)", keep_stopped);
    
    if (m_comm.IsRunning())
    {
        // We are running and we can't interrupt a running kernel, so we need
        // to just close the connection to the kernel and hope for the best
    }
    else
    {
        // If we are going to keep the target stopped, then don't send the disconnect message.
        if (!keep_stopped && m_comm.IsConnected())
        {
            const bool success = m_comm.SendRequestDisconnect();
            if (log)
            {
                if (success)
                    log->PutCString ("ProcessKDP::DoDetach() detach packet sent successfully");
                else
                    log->PutCString ("ProcessKDP::DoDetach() connection channel shutdown failed");
            }
            m_comm.Disconnect ();
        }
    }
    StopAsyncThread ();    
    m_comm.Clear();
    
    SetPrivateState (eStateDetached);
    ResumePrivateStateThread();
    
    //KillDebugserverProcess ();
    return error;
}

Error
ProcessKDP::DoDestroy ()
{
    // For KDP there really is no difference between destroy and detach
    bool keep_stopped = false;
    return DoDetach(keep_stopped);
}

//------------------------------------------------------------------
// Process Queries
//------------------------------------------------------------------

bool
ProcessKDP::IsAlive ()
{
    return m_comm.IsConnected() && Process::IsAlive();
}

//------------------------------------------------------------------
// Process Memory
//------------------------------------------------------------------
size_t
ProcessKDP::DoReadMemory (addr_t addr, void *buf, size_t size, Error &error)
{
    uint8_t *data_buffer = (uint8_t *) buf;
    if (m_comm.IsConnected())
    {
        const size_t max_read_size = 512;
        size_t total_bytes_read = 0;

        // Read the requested amount of memory in 512 byte chunks
        while (total_bytes_read < size)
        {
            size_t bytes_to_read_this_request = size - total_bytes_read;
            if (bytes_to_read_this_request > max_read_size)
            {
                bytes_to_read_this_request = max_read_size;
            }
            size_t bytes_read = m_comm.SendRequestReadMemory (addr + total_bytes_read, 
                                                              data_buffer + total_bytes_read, 
                                                              bytes_to_read_this_request, error);
            total_bytes_read += bytes_read;
            if (error.Fail() || bytes_read == 0)
            {
                return total_bytes_read;
            }
        }

        return total_bytes_read;
    }
    error.SetErrorString ("not connected");
    return 0;
}

size_t
ProcessKDP::DoWriteMemory (addr_t addr, const void *buf, size_t size, Error &error)
{
    if (m_comm.IsConnected())
        return m_comm.SendRequestWriteMemory (addr, buf, size, error);
    error.SetErrorString ("not connected");
    return 0;
}

lldb::addr_t
ProcessKDP::DoAllocateMemory (size_t size, uint32_t permissions, Error &error)
{
    error.SetErrorString ("memory allocation not suppported in kdp remote debugging");
    return LLDB_INVALID_ADDRESS;
}

Error
ProcessKDP::DoDeallocateMemory (lldb::addr_t addr)
{
    Error error;
    error.SetErrorString ("memory deallocation not suppported in kdp remote debugging");
    return error;
}

Error
ProcessKDP::EnableBreakpointSite (BreakpointSite *bp_site)
{
    if (m_comm.LocalBreakpointsAreSupported ())
    {
        Error error;
        if (!bp_site->IsEnabled())
        {
            if (m_comm.SendRequestBreakpoint(true, bp_site->GetLoadAddress()))
            {
                bp_site->SetEnabled(true);
                bp_site->SetType (BreakpointSite::eExternal);
            }
            else
            {
                error.SetErrorString ("KDP set breakpoint failed");
            }
        }
        return error;
    }
    return EnableSoftwareBreakpoint (bp_site);
}

Error
ProcessKDP::DisableBreakpointSite (BreakpointSite *bp_site)
{
    if (m_comm.LocalBreakpointsAreSupported ())
    {
        Error error;
        if (bp_site->IsEnabled())
        {
            BreakpointSite::Type bp_type = bp_site->GetType();
            if (bp_type == BreakpointSite::eExternal)
            {
                if (m_destroy_in_process && m_comm.IsRunning())
                {
                    // We are trying to destroy our connection and we are running
                    bp_site->SetEnabled(false);
                }
                else
                {
                    if (m_comm.SendRequestBreakpoint(false, bp_site->GetLoadAddress()))
                        bp_site->SetEnabled(false);
                    else
                        error.SetErrorString ("KDP remove breakpoint failed");
                }
            }
            else
            {
                error = DisableSoftwareBreakpoint (bp_site);
            }
        }
        return error;
    }
    return DisableSoftwareBreakpoint (bp_site);
}

Error
ProcessKDP::EnableWatchpoint (Watchpoint *wp, bool notify)
{
    Error error;
    error.SetErrorString ("watchpoints are not suppported in kdp remote debugging");
    return error;
}

Error
ProcessKDP::DisableWatchpoint (Watchpoint *wp, bool notify)
{
    Error error;
    error.SetErrorString ("watchpoints are not suppported in kdp remote debugging");
    return error;
}

void
ProcessKDP::Clear()
{
    m_thread_list.Clear();
}

Error
ProcessKDP::DoSignal (int signo)
{
    Error error;
    error.SetErrorString ("sending signals is not suppported in kdp remote debugging");
    return error;
}

void
ProcessKDP::Initialize()
{
    static std::once_flag g_once_flag;

    std::call_once(g_once_flag, []()
    {
        PluginManager::RegisterPlugin (GetPluginNameStatic(),
                                       GetPluginDescriptionStatic(),
                                       CreateInstance,
                                       DebuggerInitialize);

        Log::Callbacks log_callbacks = {
            ProcessKDPLog::DisableLog,
            ProcessKDPLog::EnableLog,
            ProcessKDPLog::ListLogCategories
        };

        Log::RegisterLogChannel (ProcessKDP::GetPluginNameStatic(), log_callbacks);
    });
}

void
ProcessKDP::DebuggerInitialize (lldb_private::Debugger &debugger)
{
    if (!PluginManager::GetSettingForProcessPlugin(debugger, PluginProperties::GetSettingName()))
    {
        const bool is_global_setting = true;
        PluginManager::CreateSettingForProcessPlugin (debugger,
                                                      GetGlobalPluginProperties()->GetValueProperties(),
                                                      ConstString ("Properties for the kdp-remote process plug-in."),
                                                      is_global_setting);
    }
}

bool
ProcessKDP::StartAsyncThread ()
{
    Log *log (ProcessKDPLog::GetLogIfAllCategoriesSet(KDP_LOG_PROCESS));
    
    if (log)
        log->Printf ("ProcessKDP::StartAsyncThread ()");

    if (m_async_thread.IsJoinable())
        return true;

    m_async_thread = ThreadLauncher::LaunchThread("<lldb.process.kdp-remote.async>", ProcessKDP::AsyncThread, this, NULL);
    return m_async_thread.IsJoinable();
}

void
ProcessKDP::StopAsyncThread ()
{
    Log *log (ProcessKDPLog::GetLogIfAllCategoriesSet(KDP_LOG_PROCESS));
    
    if (log)
        log->Printf ("ProcessKDP::StopAsyncThread ()");
    
    m_async_broadcaster.BroadcastEvent (eBroadcastBitAsyncThreadShouldExit);
    
    // Stop the stdio thread
    if (m_async_thread.IsJoinable())
        m_async_thread.Join(nullptr);
}


void *
ProcessKDP::AsyncThread (void *arg)
{
    ProcessKDP *process = (ProcessKDP*) arg;
    
    const lldb::pid_t pid = process->GetID();

    Log *log (ProcessKDPLog::GetLogIfAllCategoriesSet (KDP_LOG_PROCESS));
    if (log)
        log->Printf ("ProcessKDP::AsyncThread (arg = %p, pid = %" PRIu64 ") thread starting...", arg, pid);
    
    ListenerSP listener_sp (Listener::MakeListener("ProcessKDP::AsyncThread"));
    EventSP event_sp;
    const uint32_t desired_event_mask = eBroadcastBitAsyncContinue |
                                        eBroadcastBitAsyncThreadShouldExit;
    
    
    if (listener_sp->StartListeningForEvents (&process->m_async_broadcaster, desired_event_mask) == desired_event_mask)
    {
        bool done = false;
        while (!done)
        {
            if (log)
                log->Printf ("ProcessKDP::AsyncThread (pid = %" PRIu64 ") listener.WaitForEvent (NULL, event_sp)...",
                             pid);
            if (listener_sp->WaitForEvent (NULL, event_sp))
            {
                uint32_t event_type = event_sp->GetType();
                if (log)
                    log->Printf ("ProcessKDP::AsyncThread (pid = %" PRIu64 ") Got an event of type: %d...",
                                 pid,
                                 event_type);
                
                // When we are running, poll for 1 second to try and get an exception
                // to indicate the process has stopped. If we don't get one, check to
                // make sure no one asked us to exit
                bool is_running = false;
                DataExtractor exc_reply_packet;
                do
                {
                    switch (event_type)
                    {
                    case eBroadcastBitAsyncContinue:
                        {
                            is_running = true;
                            if (process->m_comm.WaitForPacketWithTimeoutMicroSeconds (exc_reply_packet, 1 * USEC_PER_SEC))
                            {
                                ThreadSP thread_sp (process->GetKernelThread());
                                if (thread_sp)
                                {
                                    lldb::RegisterContextSP reg_ctx_sp (thread_sp->GetRegisterContext());
                                    if (reg_ctx_sp)
                                        reg_ctx_sp->InvalidateAllRegisters();
                                    static_cast<ThreadKDP *>(thread_sp.get())->SetStopInfoFrom_KDP_EXCEPTION (exc_reply_packet);
                                }

                                // TODO: parse the stop reply packet
                                is_running = false;                                
                                process->SetPrivateState(eStateStopped);
                            }
                            else
                            {
                                // Check to see if we are supposed to exit. There is no way to
                                // interrupt a running kernel, so all we can do is wait for an
                                // exception or detach...
                                if (listener_sp->GetNextEvent(event_sp))
                                {
                                    // We got an event, go through the loop again
                                    event_type = event_sp->GetType();
                                }
                            }
                        }
                        break;
                            
                    case eBroadcastBitAsyncThreadShouldExit:
                        if (log)
                            log->Printf ("ProcessKDP::AsyncThread (pid = %" PRIu64 ") got eBroadcastBitAsyncThreadShouldExit...",
                                         pid);
                        done = true;
                        is_running = false;
                        break;
                            
                    default:
                        if (log)
                            log->Printf ("ProcessKDP::AsyncThread (pid = %" PRIu64 ") got unknown event 0x%8.8x",
                                         pid,
                                         event_type);
                        done = true;
                        is_running = false;
                        break;
                    }
                } while (is_running);
            }
            else
            {
                if (log)
                    log->Printf ("ProcessKDP::AsyncThread (pid = %" PRIu64 ") listener.WaitForEvent (NULL, event_sp) => false",
                                 pid);
                done = true;
            }
        }
    }
    
    if (log)
        log->Printf ("ProcessKDP::AsyncThread (arg = %p, pid = %" PRIu64 ") thread exiting...",
                     arg,
                     pid);

    process->m_async_thread.Reset();
    return NULL;
}


class CommandObjectProcessKDPPacketSend : public CommandObjectParsed
{
private:
    
    OptionGroupOptions m_option_group;
    OptionGroupUInt64 m_command_byte;
    OptionGroupString m_packet_data;
    
    virtual Options *
    GetOptions ()
    {
        return &m_option_group;
    }
    

public:
    CommandObjectProcessKDPPacketSend(CommandInterpreter &interpreter) :
        CommandObjectParsed (interpreter,
                             "process plugin packet send",
                             "Send a custom packet through the KDP protocol by specifying the command byte and the packet payload data. A packet will be sent with a correct header and payload, and the raw result bytes will be displayed as a string value. ",
                             NULL),
        m_option_group (interpreter),
        m_command_byte(LLDB_OPT_SET_1, true , "command", 'c', 0, eArgTypeNone, "Specify the command byte to use when sending the KDP request packet.", 0),
        m_packet_data (LLDB_OPT_SET_1, false, "payload", 'p', 0, eArgTypeNone, "Specify packet payload bytes as a hex ASCII string with no spaces or hex prefixes.", NULL)
    {
        m_option_group.Append (&m_command_byte, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
        m_option_group.Append (&m_packet_data , LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
        m_option_group.Finalize();
    }
    
    ~CommandObjectProcessKDPPacketSend ()
    {
    }
    
    bool
    DoExecute (Args& command, CommandReturnObject &result)
    {
        const size_t argc = command.GetArgumentCount();
        if (argc == 0)
        {
            if (!m_command_byte.GetOptionValue().OptionWasSet())
            {
                result.AppendError ("the --command option must be set to a valid command byte");
                result.SetStatus (eReturnStatusFailed);
            }
            else
            {
                const uint64_t command_byte = m_command_byte.GetOptionValue().GetUInt64Value(0);
                if (command_byte > 0 && command_byte <= UINT8_MAX)
                {
                    ProcessKDP *process = (ProcessKDP *)m_interpreter.GetExecutionContext().GetProcessPtr();
                    if (process)
                    {
                        const StateType state = process->GetState();
                        
                        if (StateIsStoppedState (state, true))
                        {
                            std::vector<uint8_t> payload_bytes;
                            const char *ascii_hex_bytes_cstr = m_packet_data.GetOptionValue().GetCurrentValue();
                            if (ascii_hex_bytes_cstr && ascii_hex_bytes_cstr[0])
                            {
                                StringExtractor extractor(ascii_hex_bytes_cstr);
                                const size_t ascii_hex_bytes_cstr_len = extractor.GetStringRef().size();
                                if (ascii_hex_bytes_cstr_len & 1)
                                {
                                    result.AppendErrorWithFormat ("payload data must contain an even number of ASCII hex characters: '%s'", ascii_hex_bytes_cstr);
                                    result.SetStatus (eReturnStatusFailed);
                                    return false;
                                }
                                payload_bytes.resize(ascii_hex_bytes_cstr_len/2);
                                if (extractor.GetHexBytes(&payload_bytes[0], payload_bytes.size(), '\xdd') != payload_bytes.size())
                                {
                                    result.AppendErrorWithFormat ("payload data must only contain ASCII hex characters (no spaces or hex prefixes): '%s'", ascii_hex_bytes_cstr);
                                    result.SetStatus (eReturnStatusFailed);
                                    return false;
                                }
                            }
                            Error error;
                            DataExtractor reply;
                            process->GetCommunication().SendRawRequest (command_byte,
                                                                        payload_bytes.empty() ? NULL : payload_bytes.data(),
                                                                        payload_bytes.size(),
                                                                        reply,
                                                                        error);
                            
                            if (error.Success())
                            {
                                // Copy the binary bytes into a hex ASCII string for the result
                                StreamString packet;
                                packet.PutBytesAsRawHex8(reply.GetDataStart(),
                                                         reply.GetByteSize(),
                                                         endian::InlHostByteOrder(),
                                                         endian::InlHostByteOrder());
                                result.AppendMessage(packet.GetString().c_str());
                                result.SetStatus (eReturnStatusSuccessFinishResult);
                                return true;
                            }
                            else
                            {
                                const char *error_cstr = error.AsCString();
                                if (error_cstr && error_cstr[0])
                                    result.AppendError (error_cstr);
                                else
                                    result.AppendErrorWithFormat ("unknown error 0x%8.8x", error.GetError());
                                result.SetStatus (eReturnStatusFailed);
                                return false;
                            }
                        }
                        else
                        {
                            result.AppendErrorWithFormat ("process must be stopped in order to send KDP packets, state is %s", StateAsCString (state));
                            result.SetStatus (eReturnStatusFailed);
                        }
                    }
                    else
                    {
                        result.AppendError ("invalid process");
                        result.SetStatus (eReturnStatusFailed);
                    }
                }
                else
                {
                    result.AppendErrorWithFormat ("invalid command byte 0x%" PRIx64 ", valid values are 1 - 255", command_byte);
                    result.SetStatus (eReturnStatusFailed);
                }
            }
        }
        else
        {
            result.AppendErrorWithFormat ("'%s' takes no arguments, only options.", m_cmd_name.c_str());
            result.SetStatus (eReturnStatusFailed);
        }
        return false;
    }
};

class CommandObjectProcessKDPPacket : public CommandObjectMultiword
{
private:

public:
    CommandObjectProcessKDPPacket(CommandInterpreter &interpreter) :
    CommandObjectMultiword (interpreter,
                            "process plugin packet",
                            "Commands that deal with KDP remote packets.",
                            NULL)
    {
        LoadSubCommand ("send", CommandObjectSP (new CommandObjectProcessKDPPacketSend (interpreter)));
    }
    
    ~CommandObjectProcessKDPPacket ()
    {
    }
};

class CommandObjectMultiwordProcessKDP : public CommandObjectMultiword
{
public:
    CommandObjectMultiwordProcessKDP(CommandInterpreter &interpreter)
        : CommandObjectMultiword(interpreter, "process plugin", "Commands for operating on a ProcessKDP process.",
                                 "process plugin <subcommand> [<subcommand-options>]")
    {
        LoadSubCommand ("packet", CommandObjectSP (new CommandObjectProcessKDPPacket    (interpreter)));
    }
    
    ~CommandObjectMultiwordProcessKDP ()
    {
    }
};

CommandObject *
ProcessKDP::GetPluginCommandObject()
{
    if (!m_command_sp)
        m_command_sp.reset (new CommandObjectMultiwordProcessKDP (GetTarget().GetDebugger().GetCommandInterpreter()));
    return m_command_sp.get();
}

