//===-- 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>
#include <pthread.h>
#include <pthread_np.h>
#include <stdlib.h>
#include <sys/sysctl.h>
#include <sys/types.h>
#include <sys/user.h>
#include <machine/elf.h>

// C++ Includes
#include <mutex>
#include <unordered_map>

// Other libraries and framework includes
#include "lldb/Core/PluginManager.h"
#include "lldb/Core/RegisterValue.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 "FreeBSDThread.h"
#include "Plugins/Process/POSIX/ProcessPOSIXLog.h"
#include "Plugins/Process/Utility/FreeBSDSignals.h"
#include "Plugins/Process/Utility/InferiorCallPOSIX.h"
#include "ProcessFreeBSD.h"
#include "ProcessMonitor.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/Host.h"
#include "lldb/Symbol/ObjectFile.h"
#include "lldb/Target/DynamicLoader.h"
#include "lldb/Target/Platform.h"
#include "lldb/Target/Target.h"
#include "lldb/Utility/DataBufferHeap.h"
#include "lldb/Utility/FileSpec.h"

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

#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Threading.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,
                               lldb::ListenerSP listener_sp,
                               const FileSpec *crash_file_path) {
  lldb::ProcessSP process_sp;
  if (crash_file_path == NULL)
    process_sp.reset(
        new ProcessFreeBSD(target_sp, listener_sp, GetFreeBSDSignals()));
  return process_sp;
}

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

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

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() {}

Status ProcessFreeBSD::DoDetach(bool keep_stopped) {
  Status 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;
}

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

  SetPrivateState(eStateRunning);

  std::lock_guard<std::recursive_mutex> guard(m_thread_list.GetMutex());
  bool do_step = false;
  bool software_single_step = !SupportHardwareSingleStepping();

  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;
    if (software_single_step) {
      Status error = SetupSoftwareSingleStepping(*t_pos);
      if (error.Fail())
        return error;
    }
  }
  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 && !software_single_step)
    m_monitor->SingleStep(GetID(), m_resume_signo);
  else
    m_monitor->Resume(GetID(), m_resume_signo);

  return Status();
}

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;
}

Status 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) {
  std::lock_guard<std::recursive_mutex> guard(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,
                               lldb::ListenerSP listener_sp,
                               UnixSignalsSP &unix_signals_sp)
    : Process(target_sp, listener_sp, unix_signals_sp),
      m_byte_order(endian::InlHostByteOrder()), m_monitor(NULL), m_module(NULL),
      m_message_mutex(), 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;
}

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

  Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS));
  LLDB_LOGV(log, "pid = {0}", 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;
}

Status ProcessFreeBSD::WillLaunch(Module *module) {
  Status 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;
}

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

  FileSpec working_dir = launch_info.GetWorkingDirectory();
  namespace fs = llvm::sys::fs;
  if (working_dir && (!working_dir.ResolvePath() ||
                      !fs::is_directory(working_dir.GetPath()))) {
    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;
}

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

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

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

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

  return error;
}

Status ProcessFreeBSD::DoDestroy() {
  Status 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());
      Status 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));
  LLDB_LOGV(log, "message_queue size = {0}", m_message_queue.size());

  std::lock_guard<std::recursive_mutex> guard(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();
    LLDB_LOGV(log, " message_queue size = {0}, pid = {1}",
              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.
      LLDB_LOG(log, "removing thread, tid = {0}", tid);
      std::lock_guard<std::recursive_mutex> guard(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,
                                    Status &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, Status &error) {
  assert(m_monitor);
  return m_monitor->WriteMemory(vm_addr, buf, size, error);
}

addr_t ProcessFreeBSD::DoAllocateMemory(size_t size, uint32_t permissions,
                                        Status &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;
}

Status ProcessFreeBSD::DoDeallocateMemory(lldb::addr_t addr) {
  Status 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;
}

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

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

Status ProcessFreeBSD::EnableWatchpoint(Watchpoint *wp, bool notify) {
  Status 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;
    std::lock_guard<std::recursive_mutex> guard(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;
}

Status ProcessFreeBSD::DisableWatchpoint(Watchpoint *wp, bool notify) {
  Status 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;
      std::lock_guard<std::recursive_mutex> guard(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;
}

Status ProcessFreeBSD::GetWatchpointSupportInfo(uint32_t &num) {
  Status error;
  std::lock_guard<std::recursive_mutex> guard(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;
}

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

uint32_t ProcessFreeBSD::UpdateThreadListIfNeeded() {
  std::lock_guard<std::recursive_mutex> guard(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, Status &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;
  std::lock_guard<std::recursive_mutex> guard(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();
  assert(platform_sp && platform_sp->IsHost());

  int mib[4] = {CTL_KERN, KERN_PROC, KERN_PROC_AUXV, (int)m_process->GetID()};
  size_t auxv_size = AT_COUNT * sizeof(Elf_Auxinfo);
  DataBufferSP buf_sp(new DataBufferHeap(auxv_size, 0));

  if (::sysctl(mib, 4, buf_sp->GetBytes(), &auxv_size, NULL, 0) != 0) {
    perror("sysctl failed on auxv");
    buf_sp.reset();
  }

  return buf_sp;
}

struct EmulatorBaton {
  ProcessFreeBSD *m_process;
  RegisterContext *m_reg_context;

  // eRegisterKindDWARF -> RegisterValue
  std::unordered_map<uint32_t, RegisterValue> m_register_values;

  EmulatorBaton(ProcessFreeBSD *process, RegisterContext *reg_context)
      : m_process(process), m_reg_context(reg_context) {}
};

static size_t ReadMemoryCallback(EmulateInstruction *instruction, void *baton,
                                 const EmulateInstruction::Context &context,
                                 lldb::addr_t addr, void *dst, size_t length) {
  EmulatorBaton *emulator_baton = static_cast<EmulatorBaton *>(baton);

  Status error;
  size_t bytes_read =
      emulator_baton->m_process->DoReadMemory(addr, dst, length, error);
  if (!error.Success())
    bytes_read = 0;
  return bytes_read;
}

static bool ReadRegisterCallback(EmulateInstruction *instruction, void *baton,
                                 const RegisterInfo *reg_info,
                                 RegisterValue &reg_value) {
  EmulatorBaton *emulator_baton = static_cast<EmulatorBaton *>(baton);

  auto it = emulator_baton->m_register_values.find(
      reg_info->kinds[eRegisterKindDWARF]);
  if (it != emulator_baton->m_register_values.end()) {
    reg_value = it->second;
    return true;
  }

  // The emulator only fills in the dwarf register numbers (and in some cases
  // the generic register numbers). Get the full register info from the
  // register context based on the dwarf register numbers.
  const RegisterInfo *full_reg_info =
      emulator_baton->m_reg_context->GetRegisterInfo(
          eRegisterKindDWARF, reg_info->kinds[eRegisterKindDWARF]);

  bool error =
      emulator_baton->m_reg_context->ReadRegister(full_reg_info, reg_value);
  return error;
}

static bool WriteRegisterCallback(EmulateInstruction *instruction, void *baton,
                                  const EmulateInstruction::Context &context,
                                  const RegisterInfo *reg_info,
                                  const RegisterValue &reg_value) {
  EmulatorBaton *emulator_baton = static_cast<EmulatorBaton *>(baton);
  emulator_baton->m_register_values[reg_info->kinds[eRegisterKindDWARF]] =
      reg_value;
  return true;
}

static size_t WriteMemoryCallback(EmulateInstruction *instruction, void *baton,
                                  const EmulateInstruction::Context &context,
                                  lldb::addr_t addr, const void *dst,
                                  size_t length) {
  return length;
}

bool ProcessFreeBSD::SingleStepBreakpointHit(
    void *baton, lldb_private::StoppointCallbackContext *context,
    lldb::user_id_t break_id, lldb::user_id_t break_loc_id) {
  return false;
}

Status ProcessFreeBSD::SetSoftwareSingleStepBreakpoint(lldb::tid_t tid,
                                                       lldb::addr_t addr) {
  Status error;

  Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS));
  if (log) {
    log->Printf("ProcessFreeBSD::%s addr = 0x%" PRIx64, __FUNCTION__, addr);
    log->Printf("SoftwareBreakpoint::%s addr = 0x%" PRIx64, __FUNCTION__, addr);
  }

  // Validate the address.
  if (addr == LLDB_INVALID_ADDRESS)
    return Status("ProcessFreeBSD::%s invalid load address specified.",
                  __FUNCTION__);

  Breakpoint *const sw_step_break =
      m_process->GetTarget().CreateBreakpoint(addr, true, false).get();
  sw_step_break->SetCallback(SingleStepBreakpointHit, this, true);
  sw_step_break->SetBreakpointKind("software-signle-step");

  if (log)
    log->Printf("ProcessFreeBSD::%s addr = 0x%" PRIx64 " -- SUCCESS",
                __FUNCTION__, addr);

  m_threads_stepping_with_breakpoint.insert({tid, sw_step_break->GetID()});
  return Status();
}

bool ProcessFreeBSD::IsSoftwareStepBreakpoint(lldb::tid_t tid) {
  ThreadSP thread = GetThreadList().FindThreadByID(tid);
  if (!thread)
    return false;

  assert(thread->GetRegisterContext());
  lldb::addr_t stop_pc = thread->GetRegisterContext()->GetPC();

  const auto &iter = m_threads_stepping_with_breakpoint.find(tid);
  if (iter == m_threads_stepping_with_breakpoint.end())
    return false;

  lldb::break_id_t bp_id = iter->second;
  BreakpointSP bp = GetTarget().GetBreakpointByID(bp_id);
  if (!bp)
    return false;

  BreakpointLocationSP bp_loc = bp->FindLocationByAddress(stop_pc);
  if (!bp_loc)
    return false;

  GetTarget().RemoveBreakpointByID(bp_id);
  m_threads_stepping_with_breakpoint.erase(tid);
  return true;
}

bool ProcessFreeBSD::SupportHardwareSingleStepping() const {
  lldb_private::ArchSpec arch = GetTarget().GetArchitecture();
  if (arch.GetMachine() == llvm::Triple::arm ||
      arch.GetMachine() == llvm::Triple::mips64 ||
      arch.GetMachine() == llvm::Triple::mips64el ||
      arch.GetMachine() == llvm::Triple::mips ||
      arch.GetMachine() == llvm::Triple::mipsel)
    return false;
  return true;
}

Status ProcessFreeBSD::SetupSoftwareSingleStepping(lldb::tid_t tid) {
  std::unique_ptr<EmulateInstruction> emulator_ap(
      EmulateInstruction::FindPlugin(GetTarget().GetArchitecture(),
                                     eInstructionTypePCModifying, nullptr));

  if (emulator_ap == nullptr)
    return Status("Instruction emulator not found!");

  FreeBSDThread *thread = static_cast<FreeBSDThread *>(
      m_thread_list.FindThreadByID(tid, false).get());
  if (thread == NULL)
    return Status("Thread not found not found!");

  lldb::RegisterContextSP register_context_sp = thread->GetRegisterContext();

  EmulatorBaton baton(this, register_context_sp.get());
  emulator_ap->SetBaton(&baton);
  emulator_ap->SetReadMemCallback(&ReadMemoryCallback);
  emulator_ap->SetReadRegCallback(&ReadRegisterCallback);
  emulator_ap->SetWriteMemCallback(&WriteMemoryCallback);
  emulator_ap->SetWriteRegCallback(&WriteRegisterCallback);

  if (!emulator_ap->ReadInstruction())
    return Status("Read instruction failed!");

  bool emulation_result =
      emulator_ap->EvaluateInstruction(eEmulateInstructionOptionAutoAdvancePC);
  const RegisterInfo *reg_info_pc = register_context_sp->GetRegisterInfo(
      eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC);
  auto pc_it =
      baton.m_register_values.find(reg_info_pc->kinds[eRegisterKindDWARF]);

  lldb::addr_t next_pc;
  if (emulation_result) {
    assert(pc_it != baton.m_register_values.end() &&
           "Emulation was successful but PC wasn't updated");
    next_pc = pc_it->second.GetAsUInt64();
  } else if (pc_it == baton.m_register_values.end()) {
    // Emulate instruction failed and it haven't changed PC. Advance PC
    // with the size of the current opcode because the emulation of all
    // PC modifying instruction should be successful. The failure most
    // likely caused by a not supported instruction which don't modify PC.
    next_pc =
        register_context_sp->GetPC() + emulator_ap->GetOpcode().GetByteSize();
  } else {
    // The instruction emulation failed after it modified the PC. It is an
    // unknown error where we can't continue because the next instruction is
    // modifying the PC but we don't  know how.
    return Status("Instruction emulation failed unexpectedly");
  }

  SetSoftwareSingleStepBreakpoint(tid, next_pc);
  return Status();
}
