//===-- 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.GetEnvironment(), 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 = AddressClass::eUnknown;

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

    if (addr_class == AddressClass::eCodeAlternateISA ||
        (addr_class == AddressClass::eUnknown &&
         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);
}

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