//===-- ProcessFreeBSD.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>

// C++ Includes
#include <mutex>

// Other libraries and framework includes
#include "lldb/Core/PluginManager.h"
#include "lldb/Core/State.h"
#include "lldb/Host/Host.h"
#include "lldb/Symbol/ObjectFile.h"
#include "lldb/Target/DynamicLoader.h"
#include "lldb/Target/Target.h"

#include "ProcessFreeBSD.h"
#include "ProcessPOSIXLog.h"
#include "Plugins/Process/Utility/InferiorCallPOSIX.h"
#include "Plugins/Process/Utility/FreeBSDSignals.h"
#include "ProcessMonitor.h"
#include "FreeBSDThread.h"

// Other libraries and framework includes
#include "lldb/Breakpoint/BreakpointLocation.h"
#include "lldb/Breakpoint/Watchpoint.h"
#include "lldb/Core/Module.h"
#include "lldb/Core/ModuleSpec.h"
#include "lldb/Core/PluginManager.h"
#include "lldb/Core/State.h"
#include "lldb/Host/FileSpec.h"
#include "lldb/Host/Host.h"
#include "lldb/Symbol/ObjectFile.h"
#include "lldb/Target/DynamicLoader.h"
#include "lldb/Target/Platform.h"
#include "lldb/Target/Target.h"

#include "lldb/Host/posix/Fcntl.h"


using namespace lldb;
using namespace lldb_private;

namespace
{
    UnixSignalsSP&
    GetFreeBSDSignals ()
    {
        static UnixSignalsSP s_freebsd_signals_sp (new FreeBSDSignals ());
        return s_freebsd_signals_sp;
    }
}

//------------------------------------------------------------------------------
// Static functions.

lldb::ProcessSP
ProcessFreeBSD::CreateInstance(lldb::TargetSP target_sp,
                               Listener &listener,
                               const FileSpec *crash_file_path)
{
    lldb::ProcessSP process_sp;
    if (crash_file_path == NULL)
        process_sp.reset(new ProcessFreeBSD (target_sp, listener, GetFreeBSDSignals()));
    return process_sp;
}

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

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

lldb_private::ConstString
ProcessFreeBSD::GetPluginNameStatic()
{
    static ConstString g_name("freebsd");
    return g_name;
}

const char *
ProcessFreeBSD::GetPluginDescriptionStatic()
{
    return "Process plugin for FreeBSD";
}

//------------------------------------------------------------------------------
// ProcessInterface protocol.

lldb_private::ConstString
ProcessFreeBSD::GetPluginName()
{
    return GetPluginNameStatic();
}

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

void
ProcessFreeBSD::Terminate()
{
}

Error
ProcessFreeBSD::DoDetach(bool keep_stopped)
{
    Error error;
    if (keep_stopped)
    {
        error.SetErrorString("Detaching with keep_stopped true is not currently supported on FreeBSD.");
        return error;
    }

    error = m_monitor->Detach(GetID());

    if (error.Success())
        SetPrivateState(eStateDetached);

    return error;
}

Error
ProcessFreeBSD::DoResume()
{
    Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_PROCESS));

    SetPrivateState(eStateRunning);

    Mutex::Locker lock(m_thread_list.GetMutex());
    bool do_step = false;

    for (tid_collection::const_iterator t_pos = m_run_tids.begin(), t_end = m_run_tids.end(); t_pos != t_end; ++t_pos)
    {
        m_monitor->ThreadSuspend(*t_pos, false);
    }
    for (tid_collection::const_iterator t_pos = m_step_tids.begin(), t_end = m_step_tids.end(); t_pos != t_end; ++t_pos)
    {
        m_monitor->ThreadSuspend(*t_pos, false);
        do_step = true;
    }
    for (tid_collection::const_iterator t_pos = m_suspend_tids.begin(), t_end = m_suspend_tids.end(); t_pos != t_end; ++t_pos)
    {
        m_monitor->ThreadSuspend(*t_pos, true);
        // XXX Cannot PT_CONTINUE properly with suspended threads.
        do_step = true;
    }

    if (log)
        log->Printf("process %" PRIu64 " resuming (%s)", GetID(), do_step ? "step" : "continue");
    if (do_step)
        m_monitor->SingleStep(GetID(), m_resume_signo);
    else
        m_monitor->Resume(GetID(), m_resume_signo);

    return Error();
}

bool
ProcessFreeBSD::UpdateThreadList(ThreadList &old_thread_list, ThreadList &new_thread_list)
{
    Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_PROCESS));
    if (log)
        log->Printf("ProcessFreeBSD::%s (pid = %" PRIu64 ")", __FUNCTION__, GetID());

    std::vector<lldb::pid_t> tds;
    if (!GetMonitor().GetCurrentThreadIDs(tds))
    {
        return false;
    }

    ThreadList old_thread_list_copy(old_thread_list);
    for (size_t i = 0; i < tds.size(); ++i)
    {
        tid_t tid = tds[i];
        ThreadSP thread_sp (old_thread_list_copy.RemoveThreadByID(tid, false));
        if (!thread_sp)
        {
            thread_sp.reset(new FreeBSDThread(*this, tid));
            if (log)
                log->Printf("ProcessFreeBSD::%s new tid = %" PRIu64, __FUNCTION__, tid);
        }
        else
        {
            if (log)
                log->Printf("ProcessFreeBSD::%s existing tid = %" PRIu64, __FUNCTION__, tid);
        }
        new_thread_list.AddThread(thread_sp);
    }
    for (size_t i = 0; i < old_thread_list_copy.GetSize(false); ++i)
    {
        ThreadSP old_thread_sp(old_thread_list_copy.GetThreadAtIndex(i, false));
        if (old_thread_sp)
        {
            if (log)
                log->Printf("ProcessFreeBSD::%s remove tid", __FUNCTION__);
        }
    }

    return true;
}

Error
ProcessFreeBSD::WillResume()
{
    m_resume_signo = 0;
    m_suspend_tids.clear();
    m_run_tids.clear();
    m_step_tids.clear();
    return Process::WillResume();
}

void
ProcessFreeBSD::SendMessage(const ProcessMessage &message)
{
    Mutex::Locker lock(m_message_mutex);

    switch (message.GetKind())
    {
    case ProcessMessage::eInvalidMessage:
        return;

    case ProcessMessage::eAttachMessage:
        SetPrivateState(eStateStopped);
        return;

    case ProcessMessage::eLimboMessage:
    case ProcessMessage::eExitMessage:
        SetExitStatus(message.GetExitStatus(), NULL);
        break;

    case ProcessMessage::eSignalMessage:
    case ProcessMessage::eSignalDeliveredMessage:
    case ProcessMessage::eBreakpointMessage:
    case ProcessMessage::eTraceMessage:
    case ProcessMessage::eWatchpointMessage:
    case ProcessMessage::eCrashMessage:
        SetPrivateState(eStateStopped);
        break;

    case ProcessMessage::eNewThreadMessage:
        llvm_unreachable("eNewThreadMessage unexpected on FreeBSD");
        break;

    case ProcessMessage::eExecMessage:
        SetPrivateState(eStateStopped);
        break;
    }

    m_message_queue.push(message);
}

//------------------------------------------------------------------------------
// Constructors and destructors.

ProcessFreeBSD::ProcessFreeBSD(lldb::TargetSP target_sp, Listener &listener, UnixSignalsSP &unix_signals_sp)
    : Process(target_sp, listener, unix_signals_sp),
      m_byte_order(endian::InlHostByteOrder()),
      m_monitor(NULL),
      m_module(NULL),
      m_message_mutex (Mutex::eMutexTypeRecursive),
      m_exit_now(false),
      m_seen_initial_stop(),
      m_resume_signo(0)
{
    // FIXME: Putting this code in the ctor and saving the byte order in a
    // member variable is a hack to avoid const qual issues in GetByteOrder.
    lldb::ModuleSP module = GetTarget().GetExecutableModule();
    if (module && module->GetObjectFile())
        m_byte_order = module->GetObjectFile()->GetByteOrder();
}

ProcessFreeBSD::~ProcessFreeBSD()
{
    delete m_monitor;
}

//------------------------------------------------------------------------------
// Process protocol.
void
ProcessFreeBSD::Finalize()
{
  Process::Finalize();

  if (m_monitor)
    m_monitor->StopMonitor();
}

bool
ProcessFreeBSD::CanDebug(lldb::TargetSP target_sp, bool plugin_specified_by_name)
{
    // For now we are just making sure the file exists for a given module
    ModuleSP exe_module_sp(target_sp->GetExecutableModule());
    if (exe_module_sp.get())
        return exe_module_sp->GetFileSpec().Exists();
    // If there is no executable module, we return true since we might be preparing to attach.
    return true;
}

Error
ProcessFreeBSD::DoAttachToProcessWithID (lldb::pid_t pid,  const ProcessAttachInfo &attach_info)
{
    Error error;
    assert(m_monitor == NULL);

    Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_PROCESS));
    if (log && log->GetMask().Test(POSIX_LOG_VERBOSE))
        log->Printf ("ProcessFreeBSD::%s(pid = %" PRIi64 ")", __FUNCTION__, GetID());

    m_monitor = new ProcessMonitor(this, pid, error);

    if (!error.Success())
        return error;

    PlatformSP platform_sp (GetTarget().GetPlatform ());
    assert (platform_sp.get());
    if (!platform_sp)
        return error;  // FIXME: Detatch?

    // Find out what we can about this process
    ProcessInstanceInfo process_info;
    platform_sp->GetProcessInfo (pid, process_info);

    // Resolve the executable module
    ModuleSP exe_module_sp;
    FileSpecList executable_search_paths (Target::GetDefaultExecutableSearchPaths());
    ModuleSpec exe_module_spec(process_info.GetExecutableFile(), GetTarget().GetArchitecture());
    error = platform_sp->ResolveExecutable(exe_module_spec,
                                           exe_module_sp,
                                           executable_search_paths.GetSize() ? &executable_search_paths : NULL);
    if (!error.Success())
        return error;

    // Fix the target architecture if necessary
    const ArchSpec &module_arch = exe_module_sp->GetArchitecture();
    if (module_arch.IsValid() && !GetTarget().GetArchitecture().IsExactMatch(module_arch))
        GetTarget().SetArchitecture(module_arch);

    // Initialize the target module list
    GetTarget().SetExecutableModule (exe_module_sp, true);

    SetSTDIOFileDescriptor(m_monitor->GetTerminalFD());

    SetID(pid);

    return error;
}

Error
ProcessFreeBSD::WillLaunch(Module* module)
{
    Error error;
    return error;
}

FileSpec
ProcessFreeBSD::GetFileSpec(const lldb_private::FileAction *file_action,
                          const FileSpec &default_file_spec,
                          const FileSpec &dbg_pts_file_spec)
{
    FileSpec file_spec{};

    if (file_action && file_action->GetAction() == FileAction::eFileActionOpen)
    {
        file_spec = file_action->GetFileSpec();
        // By default the stdio paths passed in will be pseudo-terminal
        // (/dev/pts). If so, convert to using a different default path
        // instead to redirect I/O to the debugger console. This should
        // also handle user overrides to /dev/null or a different file.
        if (!file_spec || file_spec == dbg_pts_file_spec)
            file_spec = default_file_spec;
    }
    return file_spec;
}

Error
ProcessFreeBSD::DoLaunch (Module *module,
                        ProcessLaunchInfo &launch_info)
{
    Error error;
    assert(m_monitor == NULL);

    FileSpec working_dir = launch_info.GetWorkingDirectory();
    if (working_dir &&
            (!working_dir.ResolvePath() ||
             working_dir.GetFileType() != FileSpec::eFileTypeDirectory))
    {
        error.SetErrorStringWithFormat("No such file or directory: %s",
                working_dir.GetCString());
        return error;
    }

    SetPrivateState(eStateLaunching);

    const lldb_private::FileAction *file_action;

    // Default of empty will mean to use existing open file descriptors
    FileSpec stdin_file_spec{};
    FileSpec stdout_file_spec{};
    FileSpec stderr_file_spec{};

    const FileSpec dbg_pts_file_spec{launch_info.GetPTY().GetSlaveName(NULL,0), false};

    file_action = launch_info.GetFileActionForFD (STDIN_FILENO);
    stdin_file_spec = GetFileSpec(file_action, stdin_file_spec, dbg_pts_file_spec);

    file_action = launch_info.GetFileActionForFD (STDOUT_FILENO);
    stdout_file_spec = GetFileSpec(file_action, stdout_file_spec, dbg_pts_file_spec);

    file_action = launch_info.GetFileActionForFD (STDERR_FILENO);
    stderr_file_spec = GetFileSpec(file_action, stderr_file_spec, dbg_pts_file_spec);

    m_monitor = new ProcessMonitor(this,
                                   module,
                                   launch_info.GetArguments().GetConstArgumentVector(),
                                   launch_info.GetEnvironmentEntries().GetConstArgumentVector(),
                                   stdin_file_spec,
                                   stdout_file_spec,
                                   stderr_file_spec,
                                   working_dir,
                                   launch_info,
                                   error);

    m_module = module;

    if (!error.Success())
        return error;

    int terminal = m_monitor->GetTerminalFD();
    if (terminal >= 0) {
        // The reader thread will close the file descriptor when done, so we pass it a copy.
#ifdef F_DUPFD_CLOEXEC
        int stdio = fcntl(terminal, F_DUPFD_CLOEXEC, 0);
        if (stdio == -1) {
            error.SetErrorToErrno();
            return error;
        }
#else
        // Special case when F_DUPFD_CLOEXEC does not exist (Debian kFreeBSD)
        int stdio = fcntl(terminal, F_DUPFD, 0);
        if (stdio == -1) {
            error.SetErrorToErrno();
            return error;
        }
        stdio = fcntl(terminal, F_SETFD, FD_CLOEXEC);
        if (stdio == -1) {
            error.SetErrorToErrno();
            return error;
        }
#endif
        SetSTDIOFileDescriptor(stdio);
    }

    SetID(m_monitor->GetPID());
    return error;
}

void
ProcessFreeBSD::DidLaunch()
{
}

addr_t
ProcessFreeBSD::GetImageInfoAddress()
{
    Target *target = &GetTarget();
    ObjectFile *obj_file = target->GetExecutableModule()->GetObjectFile();
    Address addr = obj_file->GetImageInfoAddress(target);

    if (addr.IsValid())
        return addr.GetLoadAddress(target);
    return LLDB_INVALID_ADDRESS;
}

Error
ProcessFreeBSD::DoHalt(bool &caused_stop)
{
    Error error;

    if (IsStopped())
    {
        caused_stop = false;
    }
    else if (kill(GetID(), SIGSTOP))
    {
        caused_stop = false;
        error.SetErrorToErrno();
    }
    else
    {
        caused_stop = true;
    }
    return error;
}

Error
ProcessFreeBSD::DoSignal(int signal)
{
    Error error;

    if (kill(GetID(), signal))
        error.SetErrorToErrno();

    return error;
}

Error
ProcessFreeBSD::DoDestroy()
{
    Error error;

    if (!HasExited())
    {
        assert(m_monitor);
        m_exit_now = true;
        if (GetID() == LLDB_INVALID_PROCESS_ID)
        {
            error.SetErrorString("invalid process id");
            return error;
        }
        if (!m_monitor->Kill())
        {
            error.SetErrorToErrno();
            return error;
        }

        SetPrivateState(eStateExited);
    }

    return error;
}

void
ProcessFreeBSD::DoDidExec()
{
    Target *target = &GetTarget();
    if (target)
    {
        PlatformSP platform_sp (target->GetPlatform());
        assert (platform_sp.get());
        if (platform_sp)
        {
            ProcessInstanceInfo process_info;
            platform_sp->GetProcessInfo(GetID(), process_info);
            ModuleSP exe_module_sp;
            ModuleSpec exe_module_spec(process_info.GetExecutableFile(), target->GetArchitecture());
            FileSpecList executable_search_paths (Target::GetDefaultExecutableSearchPaths());
            Error error = platform_sp->ResolveExecutable(exe_module_spec,
                                                         exe_module_sp,
                                                         executable_search_paths.GetSize() ? &executable_search_paths : NULL);
            if (!error.Success())
                return;
            target->SetExecutableModule(exe_module_sp, true);
        }
    }
}

bool
ProcessFreeBSD::AddThreadForInitialStopIfNeeded(lldb::tid_t stop_tid)
{
    bool added_to_set = false;
    ThreadStopSet::iterator it = m_seen_initial_stop.find(stop_tid);
    if (it == m_seen_initial_stop.end())
    {
        m_seen_initial_stop.insert(stop_tid);
        added_to_set = true;
    }
    return added_to_set;
}

bool
ProcessFreeBSD::WaitingForInitialStop(lldb::tid_t stop_tid)
{
    return (m_seen_initial_stop.find(stop_tid) == m_seen_initial_stop.end());
}

FreeBSDThread *
ProcessFreeBSD::CreateNewFreeBSDThread(lldb_private::Process &process, lldb::tid_t tid)
{
    return new FreeBSDThread(process, tid);
}

void
ProcessFreeBSD::RefreshStateAfterStop()
{
    Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_PROCESS));
    if (log && log->GetMask().Test(POSIX_LOG_VERBOSE))
        log->Printf ("ProcessFreeBSD::%s(), message_queue size = %d", __FUNCTION__, (int)m_message_queue.size());

    Mutex::Locker lock(m_message_mutex);

    // This method used to only handle one message.  Changing it to loop allows
    // it to handle the case where we hit a breakpoint while handling a different
    // breakpoint.
    while (!m_message_queue.empty())
    {
        ProcessMessage &message = m_message_queue.front();

        // Resolve the thread this message corresponds to and pass it along.
        lldb::tid_t tid = message.GetTID();
        if (log)
            log->Printf ("ProcessFreeBSD::%s(), message_queue size = %d, pid = %" PRIi64, __FUNCTION__, (int)m_message_queue.size(), tid);

        m_thread_list.RefreshStateAfterStop();

        FreeBSDThread *thread = static_cast<FreeBSDThread*>(
            GetThreadList().FindThreadByID(tid, false).get());
        if (thread)
            thread->Notify(message);

        if (message.GetKind() == ProcessMessage::eExitMessage)
        {
            // FIXME: We should tell the user about this, but the limbo message is probably better for that.
            if (log)
                log->Printf ("ProcessFreeBSD::%s() removing thread, tid = %" PRIi64, __FUNCTION__, tid);

            Mutex::Locker lock(m_thread_list.GetMutex());

            ThreadSP thread_sp = m_thread_list.RemoveThreadByID(tid, false);
            thread_sp.reset();
            m_seen_initial_stop.erase(tid);
        }

        m_message_queue.pop();
    }
}

bool
ProcessFreeBSD::IsAlive()
{
    StateType state = GetPrivateState();
    return state != eStateDetached
        && state != eStateExited
        && state != eStateInvalid
        && state != eStateUnloaded;
}

size_t
ProcessFreeBSD::DoReadMemory(addr_t vm_addr,
                           void *buf, size_t size, Error &error)
{
    assert(m_monitor);
    return m_monitor->ReadMemory(vm_addr, buf, size, error);
}

size_t
ProcessFreeBSD::DoWriteMemory(addr_t vm_addr, const void *buf, size_t size,
                            Error &error)
{
    assert(m_monitor);
    return m_monitor->WriteMemory(vm_addr, buf, size, error);
}

addr_t
ProcessFreeBSD::DoAllocateMemory(size_t size, uint32_t permissions,
                               Error &error)
{
    addr_t allocated_addr = LLDB_INVALID_ADDRESS;

    unsigned prot = 0;
    if (permissions & lldb::ePermissionsReadable)
        prot |= eMmapProtRead;
    if (permissions & lldb::ePermissionsWritable)
        prot |= eMmapProtWrite;
    if (permissions & lldb::ePermissionsExecutable)
        prot |= eMmapProtExec;

    if (InferiorCallMmap(this, allocated_addr, 0, size, prot,
                         eMmapFlagsAnon | eMmapFlagsPrivate, -1, 0)) {
        m_addr_to_mmap_size[allocated_addr] = size;
        error.Clear();
    } else {
        allocated_addr = LLDB_INVALID_ADDRESS;
        error.SetErrorStringWithFormat("unable to allocate %zu bytes of memory with permissions %s", size, GetPermissionsAsCString (permissions));
    }

    return allocated_addr;
}

Error
ProcessFreeBSD::DoDeallocateMemory(lldb::addr_t addr)
{
    Error error;
    MMapMap::iterator pos = m_addr_to_mmap_size.find(addr);
    if (pos != m_addr_to_mmap_size.end() &&
        InferiorCallMunmap(this, addr, pos->second))
        m_addr_to_mmap_size.erase (pos);
    else
        error.SetErrorStringWithFormat("unable to deallocate memory at 0x%" PRIx64, addr);

    return error;
}

size_t
ProcessFreeBSD::GetSoftwareBreakpointTrapOpcode(BreakpointSite* bp_site)
{
    static const uint8_t g_aarch64_opcode[] = { 0x00, 0x00, 0x20, 0xD4 };
    static const uint8_t g_i386_opcode[] = { 0xCC };

    ArchSpec arch = GetTarget().GetArchitecture();
    const uint8_t *opcode = NULL;
    size_t opcode_size = 0;

    switch (arch.GetMachine())
    {
    default:
        assert(false && "CPU type not supported!");
        break;

    case llvm::Triple::arm:
        {
            // The ARM reference recommends the use of 0xe7fddefe and 0xdefe
            // but the linux kernel does otherwise.
            static const uint8_t g_arm_breakpoint_opcode[] = { 0xf0, 0x01, 0xf0, 0xe7 };
            static const uint8_t g_thumb_breakpoint_opcode[] = { 0x01, 0xde };

            lldb::BreakpointLocationSP bp_loc_sp (bp_site->GetOwnerAtIndex (0));
            AddressClass addr_class = eAddressClassUnknown;

            if (bp_loc_sp)
                addr_class = bp_loc_sp->GetAddress ().GetAddressClass ();

            if (addr_class == eAddressClassCodeAlternateISA
                || (addr_class == eAddressClassUnknown
                    && bp_loc_sp->GetAddress().GetOffset() & 1))
            {
                opcode = g_thumb_breakpoint_opcode;
                opcode_size = sizeof(g_thumb_breakpoint_opcode);
            }
            else
            {
                opcode = g_arm_breakpoint_opcode;
                opcode_size = sizeof(g_arm_breakpoint_opcode);
            }
        }
        break;
    case llvm::Triple::aarch64:
        opcode = g_aarch64_opcode;
        opcode_size = sizeof(g_aarch64_opcode);
        break;

    case llvm::Triple::x86:
    case llvm::Triple::x86_64:
        opcode = g_i386_opcode;
        opcode_size = sizeof(g_i386_opcode);
        break;
    }

    bp_site->SetTrapOpcode(opcode, opcode_size);
    return opcode_size;
}

Error
ProcessFreeBSD::EnableBreakpointSite(BreakpointSite *bp_site)
{
    return EnableSoftwareBreakpoint(bp_site);
}

Error
ProcessFreeBSD::DisableBreakpointSite(BreakpointSite *bp_site)
{
    return DisableSoftwareBreakpoint(bp_site);
}

Error
ProcessFreeBSD::EnableWatchpoint(Watchpoint *wp, bool notify)
{
    Error error;
    if (wp)
    {
        user_id_t watchID = wp->GetID();
        addr_t addr = wp->GetLoadAddress();
        Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_WATCHPOINTS));
        if (log)
            log->Printf ("ProcessFreeBSD::EnableWatchpoint(watchID = %" PRIu64 ")",
                         watchID);
        if (wp->IsEnabled())
        {
            if (log)
                log->Printf("ProcessFreeBSD::EnableWatchpoint(watchID = %" PRIu64
                            ") addr = 0x%8.8" PRIx64 ": watchpoint already enabled.",
                            watchID, (uint64_t)addr);
            return error;
        }

        // Try to find a vacant watchpoint slot in the inferiors' main thread
        uint32_t wp_hw_index = LLDB_INVALID_INDEX32;
        Mutex::Locker lock(m_thread_list.GetMutex());
        FreeBSDThread *thread = static_cast<FreeBSDThread*>(
                               m_thread_list.GetThreadAtIndex(0, false).get());

        if (thread)
            wp_hw_index = thread->FindVacantWatchpointIndex();

        if (wp_hw_index == LLDB_INVALID_INDEX32)
        {
            error.SetErrorString("Setting hardware watchpoint failed.");
        }
        else
        {
            wp->SetHardwareIndex(wp_hw_index);
            bool wp_enabled = true;
            uint32_t thread_count = m_thread_list.GetSize(false);
            for (uint32_t i = 0; i < thread_count; ++i)
            {
                thread = static_cast<FreeBSDThread*>(
                         m_thread_list.GetThreadAtIndex(i, false).get());
                if (thread)
                    wp_enabled &= thread->EnableHardwareWatchpoint(wp);
                else
                    wp_enabled = false;
            }
            if (wp_enabled)
            {
                wp->SetEnabled(true, notify);
                return error;
            }
            else
            {
                // Watchpoint enabling failed on at least one
                // of the threads so roll back all of them
                DisableWatchpoint(wp, false);
                error.SetErrorString("Setting hardware watchpoint failed");
            }
        }
    }
    else
        error.SetErrorString("Watchpoint argument was NULL.");
    return error;
}

Error
ProcessFreeBSD::DisableWatchpoint(Watchpoint *wp, bool notify)
{
    Error error;
    if (wp)
    {
        user_id_t watchID = wp->GetID();
        addr_t addr = wp->GetLoadAddress();
        Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_WATCHPOINTS));
        if (log)
            log->Printf("ProcessFreeBSD::DisableWatchpoint(watchID = %" PRIu64 ")",
                        watchID);
        if (!wp->IsEnabled())
        {
            if (log)
                log->Printf("ProcessFreeBSD::DisableWatchpoint(watchID = %" PRIu64
                            ") addr = 0x%8.8" PRIx64 ": watchpoint already disabled.",
                            watchID, (uint64_t)addr);
            // This is needed (for now) to keep watchpoints disabled correctly
            wp->SetEnabled(false, notify);
            return error;
        }

        if (wp->IsHardware())
        {
            bool wp_disabled = true;
            Mutex::Locker lock(m_thread_list.GetMutex());
            uint32_t thread_count = m_thread_list.GetSize(false);
            for (uint32_t i = 0; i < thread_count; ++i)
            {
                FreeBSDThread *thread = static_cast<FreeBSDThread*>(
                                      m_thread_list.GetThreadAtIndex(i, false).get());
                if (thread)
                    wp_disabled &= thread->DisableHardwareWatchpoint(wp);
                else
                    wp_disabled = false;
            }
            if (wp_disabled)
            {
                wp->SetHardwareIndex(LLDB_INVALID_INDEX32);
                wp->SetEnabled(false, notify);
                return error;
            }
            else
                error.SetErrorString("Disabling hardware watchpoint failed");
        }
    }
    else
        error.SetErrorString("Watchpoint argument was NULL.");
    return error;
}

Error
ProcessFreeBSD::GetWatchpointSupportInfo(uint32_t &num)
{
    Error error;
    Mutex::Locker lock(m_thread_list.GetMutex());
    FreeBSDThread *thread = static_cast<FreeBSDThread*>(
                          m_thread_list.GetThreadAtIndex(0, false).get());
    if (thread)
        num = thread->NumSupportedHardwareWatchpoints();
    else
        error.SetErrorString("Process does not exist.");
    return error;
}

Error
ProcessFreeBSD::GetWatchpointSupportInfo(uint32_t &num, bool &after)
{
    Error error = GetWatchpointSupportInfo(num);
    // Watchpoints trigger and halt the inferior after
    // the corresponding instruction has been executed.
    after = true;
    return error;
}

uint32_t
ProcessFreeBSD::UpdateThreadListIfNeeded()
{
    Mutex::Locker lock(m_thread_list.GetMutex());
    // Do not allow recursive updates.
    return m_thread_list.GetSize(false);
}

#if 0
bool
ProcessFreeBSD::UpdateThreadList(ThreadList &old_thread_list, ThreadList &new_thread_list)
{
    Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_THREAD));
    if (log && log->GetMask().Test(POSIX_LOG_VERBOSE))
        log->Printf ("ProcessFreeBSD::%s() (pid = %" PRIi64 ")", __FUNCTION__, GetID());

    bool has_updated = false;
    // Update the process thread list with this new thread.
    // FIXME: We should be using tid, not pid.
    assert(m_monitor);
    ThreadSP thread_sp (old_thread_list.FindThreadByID (GetID(), false));
    if (!thread_sp) {
        thread_sp.reset(CreateNewFreeBSDThread(*this, GetID()));
        has_updated = true;
    }

    if (log && log->GetMask().Test(POSIX_LOG_VERBOSE))
        log->Printf ("ProcessFreeBSD::%s() updated pid = %" PRIi64, __FUNCTION__, GetID());
    new_thread_list.AddThread(thread_sp);

    return has_updated; // the list has been updated
}
#endif

ByteOrder
ProcessFreeBSD::GetByteOrder() const
{
    // FIXME: We should be able to extract this value directly.  See comment in
    // ProcessFreeBSD().
    return m_byte_order;
}

size_t
ProcessFreeBSD::PutSTDIN(const char *buf, size_t len, Error &error)
{
    ssize_t status;
    if ((status = write(m_monitor->GetTerminalFD(), buf, len)) < 0) 
    {
        error.SetErrorToErrno();
        return 0;
    }
    return status;
}

//------------------------------------------------------------------------------
// Utility functions.

bool
ProcessFreeBSD::HasExited()
{
    switch (GetPrivateState())
    {
    default:
        break;

    case eStateDetached:
    case eStateExited:
        return true;
    }

    return false;
}

bool
ProcessFreeBSD::IsStopped()
{
    switch (GetPrivateState())
    {
    default:
        break;

    case eStateStopped:
    case eStateCrashed:
    case eStateSuspended:
        return true;
    }

    return false;
}

bool
ProcessFreeBSD::IsAThreadRunning()
{
    bool is_running = false;
    Mutex::Locker lock(m_thread_list.GetMutex());
    uint32_t thread_count = m_thread_list.GetSize(false);
    for (uint32_t i = 0; i < thread_count; ++i)
    {
        FreeBSDThread *thread = static_cast<FreeBSDThread*>(
            m_thread_list.GetThreadAtIndex(i, false).get());
        StateType thread_state = thread->GetState();
        if (thread_state == eStateRunning || thread_state == eStateStepping)
        {
            is_running = true;
            break;
        }
    }
    return is_running;
}

const DataBufferSP
ProcessFreeBSD::GetAuxvData ()
{
    // If we're the local platform, we can ask the host for auxv data.
    PlatformSP platform_sp = GetTarget().GetPlatform ();
    if (platform_sp && platform_sp->IsHost ())
        return lldb_private::Host::GetAuxvData(this);

    // Somewhat unexpected - the process is not running locally or we don't have a platform.
    assert (false && "no platform or not the host - how did we get here with ProcessFreeBSD?");
    return DataBufferSP ();
}
