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

#include "lldb/Host/common/NativeProcessProtocol.h"

#include "lldb/lldb-enumerations.h"
#include "lldb/Core/ArchSpec.h"
#include "lldb/Core/Log.h"
#include "lldb/Core/State.h"
#include "lldb/Host/Host.h"
#include "lldb/Host/common/NativeRegisterContext.h"

#include "lldb/Host/common/NativeThreadProtocol.h"
#include "lldb/Host/common/SoftwareBreakpoint.h"

using namespace lldb;
using namespace lldb_private;

// -----------------------------------------------------------------------------
// NativeProcessProtocol Members
// -----------------------------------------------------------------------------

NativeProcessProtocol::NativeProcessProtocol (lldb::pid_t pid) :
    m_pid (pid),
    m_threads (),
    m_current_thread_id (LLDB_INVALID_THREAD_ID),
    m_threads_mutex (Mutex::eMutexTypeRecursive),
    m_state (lldb::eStateInvalid),
    m_state_mutex (Mutex::eMutexTypeRecursive),
    m_exit_type (eExitTypeInvalid),
    m_exit_status (0),
    m_exit_description (),
    m_delegates_mutex (Mutex::eMutexTypeRecursive),
    m_delegates (),
    m_breakpoint_list (),
    m_watchpoint_list (),
    m_terminal_fd (-1),
    m_stop_id (0)
{
}

lldb_private::Error
NativeProcessProtocol::Interrupt ()
{
    Error error;
#if !defined (SIGSTOP)
    error.SetErrorString ("local host does not support signaling");
    return error;
#else
    return Signal (SIGSTOP);
#endif
}

lldb_private::Error
NativeProcessProtocol::GetMemoryRegionInfo (lldb::addr_t load_addr, MemoryRegionInfo &range_info)
{
    // Default: not implemented.
    return Error ("not implemented");
}

bool
NativeProcessProtocol::GetExitStatus (ExitType *exit_type, int *status, std::string &exit_description)
{
    if (m_state == lldb::eStateExited)
    {
        *exit_type = m_exit_type;
        *status = m_exit_status;
        exit_description = m_exit_description;
        return true;
    }

    *status = 0;
    return false;
}

bool
NativeProcessProtocol::SetExitStatus (ExitType exit_type, int status, const char *exit_description, bool bNotifyStateChange)
{
    Log *log (lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS));
    if (log)
        log->Printf ("NativeProcessProtocol::%s(%d, %d, %s, %s) called",
                __FUNCTION__,
                exit_type,
                status,
                exit_description ? exit_description : "nullptr",
                bNotifyStateChange ? "true" : "false");

    // Exit status already set
    if (m_state == lldb::eStateExited)
    {
        if (log)
            log->Printf ("NativeProcessProtocol::%s exit status already set to %d, ignoring new set to %d", __FUNCTION__, m_exit_status, status);
        return false;
    }

    m_state = lldb::eStateExited;

    m_exit_type = exit_type;
    m_exit_status = status;
    if (exit_description && exit_description[0])
        m_exit_description = exit_description;
    else
        m_exit_description.clear();

    if (bNotifyStateChange)
        SynchronouslyNotifyProcessStateChanged (lldb::eStateExited);

    return true;
}

NativeThreadProtocolSP
NativeProcessProtocol::GetThreadAtIndex (uint32_t idx)
{
    Mutex::Locker locker (m_threads_mutex);
    if (idx < m_threads.size ())
        return m_threads[idx];
    return NativeThreadProtocolSP ();
}

NativeThreadProtocolSP
NativeProcessProtocol::GetThreadByIDUnlocked (lldb::tid_t tid)
{
    for (auto thread_sp : m_threads)
    {
        if (thread_sp->GetID() == tid)
            return thread_sp;
    }
    return NativeThreadProtocolSP ();
}

NativeThreadProtocolSP
NativeProcessProtocol::GetThreadByID (lldb::tid_t tid)
{
    Mutex::Locker locker (m_threads_mutex);
    return GetThreadByIDUnlocked (tid);
}

bool
NativeProcessProtocol::IsAlive () const
{
    return m_state != eStateDetached
        && m_state != eStateExited
        && m_state != eStateInvalid
        && m_state != eStateUnloaded;
}

bool
NativeProcessProtocol::GetByteOrder (lldb::ByteOrder &byte_order) const
{
    ArchSpec process_arch;
    if (!GetArchitecture (process_arch))
        return false;
    byte_order = process_arch.GetByteOrder ();
    return true;
}

const NativeWatchpointList::WatchpointMap&
NativeProcessProtocol::GetWatchpointMap () const
{
    return m_watchpoint_list.GetWatchpointMap();
}

uint32_t
NativeProcessProtocol::GetMaxWatchpoints () const
{
    // This default implementation will return the number of
    // *hardware* breakpoints available.  MacOSX and other OS
    // implementations that support software breakpoints will want to
    // override this correctly for their implementation.
    Log *log (lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS));

    // get any thread
    NativeThreadProtocolSP thread_sp (const_cast<NativeProcessProtocol*> (this)->GetThreadAtIndex (0));
    if (!thread_sp)
    {
        if (log)
            log->Warning ("NativeProcessProtocol::%s (): failed to find a thread to grab a NativeRegisterContext!", __FUNCTION__);
        return 0;
    }

    NativeRegisterContextSP reg_ctx_sp (thread_sp->GetRegisterContext ());
    if (!reg_ctx_sp)
    {
        if (log)
            log->Warning ("NativeProcessProtocol::%s (): failed to get a RegisterContextNativeProcess from the first thread!", __FUNCTION__);
        return 0;
    }

    return reg_ctx_sp->NumSupportedHardwareWatchpoints ();
}

Error
NativeProcessProtocol::SetWatchpoint (lldb::addr_t addr, size_t size, uint32_t watch_flags, bool hardware)
{
    // This default implementation assumes setting the watchpoint for
    // the process will require setting the watchpoint for each of the
    // threads.  Furthermore, it will track watchpoints set for the
    // process and will add them to each thread that is attached to
    // via the (FIXME implement) OnThreadAttached () method.

    Log *log (lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS));

    // Update the thread list
    UpdateThreads ();

    // Keep track of the threads we successfully set the watchpoint
    // for.  If one of the thread watchpoint setting operations fails,
    // back off and remove the watchpoint for all the threads that
    // were successfully set so we get back to a consistent state.
    std::vector<NativeThreadProtocolSP> watchpoint_established_threads;

    // Tell each thread to set a watchpoint.  In the event that
    // hardware watchpoints are requested but the SetWatchpoint fails,
    // try to set a software watchpoint as a fallback.  It's
    // conceivable that if there are more threads than hardware
    // watchpoints available, some of the threads will fail to set
    // hardware watchpoints while software ones may be available.
    Mutex::Locker locker (m_threads_mutex);
    for (auto thread_sp : m_threads)
    {
        assert (thread_sp && "thread list should not have a NULL thread!");
        if (!thread_sp)
            continue;

        Error thread_error = thread_sp->SetWatchpoint (addr, size, watch_flags, hardware);
        if (thread_error.Fail () && hardware)
        {
            // Try software watchpoints since we failed on hardware watchpoint setting
            // and we may have just run out of hardware watchpoints.
            thread_error = thread_sp->SetWatchpoint (addr, size, watch_flags, false);
            if (thread_error.Success ())
            {
                if (log)
                    log->Warning ("hardware watchpoint requested but software watchpoint set"); 
            }
        }

        if (thread_error.Success ())
        {
            // Remember that we set this watchpoint successfully in
            // case we need to clear it later.
            watchpoint_established_threads.push_back (thread_sp);
        }
        else
        {
            // Unset the watchpoint for each thread we successfully
            // set so that we get back to a consistent state of "not
            // set" for the watchpoint.
            for (auto unwatch_thread_sp : watchpoint_established_threads)
            {
                Error remove_error = unwatch_thread_sp->RemoveWatchpoint (addr);
                if (remove_error.Fail () && log)
                {
                    log->Warning ("NativeProcessProtocol::%s (): RemoveWatchpoint failed for pid=%" PRIu64 ", tid=%" PRIu64 ": %s",
                            __FUNCTION__, GetID (), unwatch_thread_sp->GetID (), remove_error.AsCString ());
                }
            }

            return thread_error;
        }
    }
    return m_watchpoint_list.Add (addr, size, watch_flags, hardware);
}

Error
NativeProcessProtocol::RemoveWatchpoint (lldb::addr_t addr)
{
    // Update the thread list
    UpdateThreads ();

    Error overall_error;

    Mutex::Locker locker (m_threads_mutex);
    for (auto thread_sp : m_threads)
    {
        assert (thread_sp && "thread list should not have a NULL thread!");
        if (!thread_sp)
            continue;

        const Error thread_error = thread_sp->RemoveWatchpoint (addr);
        if (thread_error.Fail ())
        {
            // Keep track of the first thread error if any threads
            // fail. We want to try to remove the watchpoint from
            // every thread, though, even if one or more have errors.
            if (!overall_error.Fail ())
                overall_error = thread_error;
        }
    }
    const Error error = m_watchpoint_list.Remove(addr);
    return overall_error.Fail() ? overall_error : error;
}

bool
NativeProcessProtocol::RegisterNativeDelegate (NativeDelegate &native_delegate)
{
    Mutex::Locker locker (m_delegates_mutex);
    if (std::find (m_delegates.begin (), m_delegates.end (), &native_delegate) != m_delegates.end ())
        return false;

    m_delegates.push_back (&native_delegate);
    native_delegate.InitializeDelegate (this);
    return true;
}

bool
NativeProcessProtocol::UnregisterNativeDelegate (NativeDelegate &native_delegate)
{
    Mutex::Locker locker (m_delegates_mutex);

    const auto initial_size = m_delegates.size ();
    m_delegates.erase (remove (m_delegates.begin (), m_delegates.end (), &native_delegate), m_delegates.end ());

    // We removed the delegate if the count of delegates shrank after
    // removing all copies of the given native_delegate from the vector.
    return m_delegates.size () < initial_size;
}

void
NativeProcessProtocol::SynchronouslyNotifyProcessStateChanged (lldb::StateType state)
{
    Log *log (GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS));

    Mutex::Locker locker (m_delegates_mutex);
    for (auto native_delegate: m_delegates)
        native_delegate->ProcessStateChanged (this, state);

    if (log)
    {
        if (!m_delegates.empty ())
        {
            log->Printf ("NativeProcessProtocol::%s: sent state notification [%s] from process %" PRIu64,
                    __FUNCTION__, lldb_private::StateAsCString (state),  GetID ());
        }
        else
        {
            log->Printf ("NativeProcessProtocol::%s: would send state notification [%s] from process %" PRIu64 ", but no delegates",
                    __FUNCTION__, lldb_private::StateAsCString (state),  GetID ());
        }
    }
}

void
NativeProcessProtocol::NotifyDidExec ()
{
    Log *log (GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS));
    if (log)
        log->Printf ("NativeProcessProtocol::%s - preparing to call delegates", __FUNCTION__);

    {
        Mutex::Locker locker (m_delegates_mutex);
        for (auto native_delegate: m_delegates)
            native_delegate->DidExec (this);
    }
}


Error
NativeProcessProtocol::SetSoftwareBreakpoint (lldb::addr_t addr, uint32_t size_hint)
{
    Log *log (GetLogIfAnyCategoriesSet (LIBLLDB_LOG_BREAKPOINTS));
    if (log)
        log->Printf ("NativeProcessProtocol::%s addr = 0x%" PRIx64, __FUNCTION__, addr);

    return m_breakpoint_list.AddRef (addr, size_hint, false,
            [this] (lldb::addr_t addr, size_t size_hint, bool /* hardware */, NativeBreakpointSP &breakpoint_sp)->Error
            { return SoftwareBreakpoint::CreateSoftwareBreakpoint (*this, addr, size_hint, breakpoint_sp); });
}

Error
NativeProcessProtocol::RemoveBreakpoint (lldb::addr_t addr)
{
    return m_breakpoint_list.DecRef (addr);
}

Error
NativeProcessProtocol::EnableBreakpoint (lldb::addr_t addr)
{
    return m_breakpoint_list.EnableBreakpoint (addr);
}

Error
NativeProcessProtocol::DisableBreakpoint (lldb::addr_t addr)
{
    return m_breakpoint_list.DisableBreakpoint (addr);
}

lldb::StateType
NativeProcessProtocol::GetState () const
{
    Mutex::Locker locker (m_state_mutex);
    return m_state;
}

void
NativeProcessProtocol::SetState (lldb::StateType state, bool notify_delegates)
{
    Mutex::Locker locker (m_state_mutex);

    if (state == m_state)
        return;

    m_state = state;

    if (StateIsStoppedState (state, false))
    {
        ++m_stop_id;

        // Give process a chance to do any stop id bump processing, such as
        // clearing cached data that is invalidated each time the process runs.
        // Note if/when we support some threads running, we'll end up needing
        // to manage this per thread and per process.
        DoStopIDBumped (m_stop_id);
    }

    // Optionally notify delegates of the state change.
    if (notify_delegates)
        SynchronouslyNotifyProcessStateChanged (state);
}

uint32_t NativeProcessProtocol::GetStopID () const
{
   Mutex::Locker locker (m_state_mutex);
   return m_stop_id;
}

void
NativeProcessProtocol::DoStopIDBumped (uint32_t /* newBumpId */)
{
    // Default implementation does nothing.
}

void
NativeProcessProtocol::Terminate ()
{
    // Default implementation does nothing.
}

#ifndef __linux__
// These need to be implemented to support lldb-gdb-server on a given platform. Stubs are
// provided to make the rest of the code link on non-supported platforms.

Error
NativeProcessProtocol::Launch (ProcessLaunchInfo &launch_info,
        NativeDelegate &native_delegate,
        NativeProcessProtocolSP &process_sp)
{
    llvm_unreachable("Platform has no NativeProcessProtocol support");
}

Error
NativeProcessProtocol::Attach (lldb::pid_t pid,
        NativeDelegate &native_delegate,
        NativeProcessProtocolSP &process_sp)
{
    llvm_unreachable("Platform has no NativeProcessProtocol support");
}

#endif
