pkgsrc-WIP-changes archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

lldb-git: Resume work on Process plugin @ NetBSD



Module Name:	pkgsrc-wip
Committed By:	Kamil Rytarowski <n54%gmx.com@localhost>
Pushed By:	kamil
Date:		Tue May 3 21:48:25 2016 +0200
Changeset:	5420d03b3b106d5ae46d70e883221d112557dc3f

Modified Files:
	lldb-git/distinfo
Added Files:
	lldb-git/patches/patch-source_Plugins_Process_CMakeLists.txt
	lldb-git/patches/patch-source_Plugins_Process_NetBSD_CMakeLists.txt
	lldb-git/patches/patch-source_Plugins_Process_NetBSD_NetBSDThread.cpp
	lldb-git/patches/patch-source_Plugins_Process_NetBSD_NetBSDThread.h
	lldb-git/patches/patch-source_Plugins_Process_NetBSD_POSIXStopInfo.cpp
	lldb-git/patches/patch-source_Plugins_Process_NetBSD_POSIXStopInfo.h
	lldb-git/patches/patch-source_Plugins_Process_NetBSD_ProcessMonitor.cpp
	lldb-git/patches/patch-source_Plugins_Process_NetBSD_ProcessMonitor.h
	lldb-git/patches/patch-source_Plugins_Process_NetBSD_ProcessNetBSD.cpp
	lldb-git/patches/patch-source_Plugins_Process_NetBSD_ProcessNetBSD.h
	lldb-git/patches/patch-source_Plugins_Process_NetBSD_RegisterContextPOSIX.h
	lldb-git/patches/patch-source_Plugins_Process_NetBSD_RegisterContextPOSIXProcessMonitor__x86.cpp
	lldb-git/patches/patch-source_Plugins_Process_NetBSD_RegisterContextPOSIXProcessMonitor__x86.h

Log Message:
lldb-git: Resume work on Process plugin @ NetBSD

To see a diff of this commit:
https://wip.pkgsrc.org/cgi-bin/gitweb.cgi?p=pkgsrc-wip.git;a=commitdiff;h=5420d03b3b106d5ae46d70e883221d112557dc3f

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

diffstat:
 lldb-git/distinfo                                  |   14 +
 .../patch-source_Plugins_Process_CMakeLists.txt    |   12 +
 ...ch-source_Plugins_Process_NetBSD_CMakeLists.txt |   17 +
 ...-source_Plugins_Process_NetBSD_NetBSDThread.cpp |  632 +++++++++
 ...ch-source_Plugins_Process_NetBSD_NetBSDThread.h |  147 +++
 ...source_Plugins_Process_NetBSD_POSIXStopInfo.cpp |   97 ++
 ...h-source_Plugins_Process_NetBSD_POSIXStopInfo.h |  115 ++
 ...ource_Plugins_Process_NetBSD_ProcessMonitor.cpp | 1349 ++++++++++++++++++++
 ...-source_Plugins_Process_NetBSD_ProcessMonitor.h |  308 +++++
 ...source_Plugins_Process_NetBSD_ProcessNetBSD.cpp |  941 ++++++++++++++
 ...h-source_Plugins_Process_NetBSD_ProcessNetBSD.h |  254 ++++
 ...e_Plugins_Process_NetBSD_RegisterContextPOSIX.h |   84 ++
 ...BSD_RegisterContextPOSIXProcessMonitor__x86.cpp |  623 +++++++++
 ...etBSD_RegisterContextPOSIXProcessMonitor__x86.h |  102 ++
 14 files changed, 4695 insertions(+)

diffs:
diff --git a/lldb-git/distinfo b/lldb-git/distinfo
index faf5775..4b2ab8e 100644
--- a/lldb-git/distinfo
+++ b/lldb-git/distinfo
@@ -20,6 +20,20 @@ SHA1 (patch-include_lldb_Utility_regex2.h) = 822a47b1221368ec5442bfbdbc20fe4e370
 SHA1 (patch-include_lldb_Utility_regex__impl.h) = 4d99669a756bd662ae28abc8cefe6e1538ef84b6
 SHA1 (patch-include_lldb_Utility_regutils.h) = ea36409f8cd05dcf9b81144cbc136abc5fc3a190
 SHA1 (patch-scripts_CMakeLists.txt) = 1f9515a9c615aab15ac6955894664e2187a5da88
+SHA1 (patch-source_Host_netbsd_HostThreadNetBSD.cpp) = 23a310a2d899d1e92008f399d59d8dd0648bdccc
+SHA1 (patch-source_Plugins_Process_CMakeLists.txt) = 895b469f32c4bec510a98d34b6af3a642523d4f2
+SHA1 (patch-source_Plugins_Process_NetBSD_CMakeLists.txt) = 86a06bff3059f5305f761f02362eed40c28537a6
+SHA1 (patch-source_Plugins_Process_NetBSD_NetBSDThread.cpp) = beaabe8555b152d95278d29bdf89a6d471ac924b
+SHA1 (patch-source_Plugins_Process_NetBSD_NetBSDThread.h) = ee37571f6aaf67c63371df3dfed1277794bb4d56
+SHA1 (patch-source_Plugins_Process_NetBSD_POSIXStopInfo.cpp) = 71110d7da7c6ad902591b8ac274577c88c140ea6
+SHA1 (patch-source_Plugins_Process_NetBSD_POSIXStopInfo.h) = 583821e5ebd35dc0612d39db00afbc09761b43b5
+SHA1 (patch-source_Plugins_Process_NetBSD_ProcessMonitor.cpp) = 41da9eccdf39fca23ea74f1913d625d4b72201d1
+SHA1 (patch-source_Plugins_Process_NetBSD_ProcessMonitor.h) = ff772445702c8fc00cbb47f93e8cda386284c5f3
+SHA1 (patch-source_Plugins_Process_NetBSD_ProcessNetBSD.cpp) = e35148da4957197ada44ad45da72e67ffe9f6b73
+SHA1 (patch-source_Plugins_Process_NetBSD_ProcessNetBSD.h) = 6e1c6a96bafd0ba7466c4551fad6990b3ada1a07
+SHA1 (patch-source_Plugins_Process_NetBSD_RegisterContextPOSIX.h) = 9eb4ccf2af59707ed532f8c23ffff9dab8c0631f
+SHA1 (patch-source_Plugins_Process_NetBSD_RegisterContextPOSIXProcessMonitor__x86.cpp) = 0aa01f8bdb096eaf4b1af5f0c729fddd3dcda648
+SHA1 (patch-source_Plugins_Process_NetBSD_RegisterContextPOSIXProcessMonitor__x86.h) = 63301063f6b73b2d06b37e44dfb98862d18575ae
 SHA1 (patch-source_Plugins_SymbolFile_PDB_CMakeLists.txt) = 3465152684eabea85f4ae6250db7bf01fe06cf90
 SHA1 (patch-source_Utility_CMakeLists.txt) = 5b10fe94d76135d8d5ba31862066841394dd45c1
 SHA1 (patch-source_Utility_regcomp.c) = bd315000773bab38b6fe6d119420afbcb5b83a59
diff --git a/lldb-git/patches/patch-source_Plugins_Process_CMakeLists.txt b/lldb-git/patches/patch-source_Plugins_Process_CMakeLists.txt
new file mode 100644
index 0000000..fa6d2da
--- /dev/null
+++ b/lldb-git/patches/patch-source_Plugins_Process_CMakeLists.txt
@@ -0,0 +1,12 @@
+$NetBSD$
+
+--- source/Plugins/Process/CMakeLists.txt.orig	2016-05-01 10:39:36.000000000 +0000
++++ source/Plugins/Process/CMakeLists.txt
+@@ -5,6 +5,7 @@ elseif (CMAKE_SYSTEM_NAME MATCHES "FreeB
+   add_subdirectory(FreeBSD)
+   add_subdirectory(POSIX)
+ elseif (CMAKE_SYSTEM_NAME MATCHES "NetBSD")
++  add_subdirectory(NetBSD)
+   add_subdirectory(POSIX)
+ elseif (CMAKE_SYSTEM_NAME MATCHES "Windows")
+   add_subdirectory(Windows/Live)
diff --git a/lldb-git/patches/patch-source_Plugins_Process_NetBSD_CMakeLists.txt b/lldb-git/patches/patch-source_Plugins_Process_NetBSD_CMakeLists.txt
new file mode 100644
index 0000000..b13c07e
--- /dev/null
+++ b/lldb-git/patches/patch-source_Plugins_Process_NetBSD_CMakeLists.txt
@@ -0,0 +1,17 @@
+$NetBSD$
+
+--- source/Plugins/Process/NetBSD/CMakeLists.txt.orig	2016-05-03 20:18:09.414601924 +0000
++++ source/Plugins/Process/NetBSD/CMakeLists.txt
+@@ -0,0 +1,12 @@
++include_directories(.)
++include_directories(../POSIX)
++include_directories(../Utility)
++
++add_lldb_library(lldbPluginProcessNetBSD
++  ProcessNetBSD.cpp
++  NetBSDThread.cpp
++  ProcessMonitor.cpp
++
++  POSIXStopInfo.cpp
++  RegisterContextPOSIXProcessMonitor_x86.cpp
++  )
diff --git a/lldb-git/patches/patch-source_Plugins_Process_NetBSD_NetBSDThread.cpp b/lldb-git/patches/patch-source_Plugins_Process_NetBSD_NetBSDThread.cpp
new file mode 100644
index 0000000..4742fca
--- /dev/null
+++ b/lldb-git/patches/patch-source_Plugins_Process_NetBSD_NetBSDThread.cpp
@@ -0,0 +1,632 @@
+$NetBSD$
+
+--- source/Plugins/Process/NetBSD/NetBSDThread.cpp.orig	2016-05-03 20:18:09.420439886 +0000
++++ source/Plugins/Process/NetBSD/NetBSDThread.cpp
+@@ -0,0 +1,627 @@
++//===-- NetBSDThread.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
++// Other libraries and framework includes
++#include "lldb/Core/State.h"
++#include "lldb/Target/UnixSignals.h"
++
++// Project includes
++#include "lldb/Breakpoint/Watchpoint.h"
++#include "lldb/Breakpoint/BreakpointLocation.h"
++#include "lldb/Core/Debugger.h"
++#include "lldb/Core/State.h"
++#include "lldb/Host/Host.h"
++#include "lldb/Host/HostNativeThread.h"
++#include "lldb/Host/HostInfo.h"
++#include "lldb/Target/Process.h"
++#include "lldb/Target/StopInfo.h"
++#include "lldb/Target/Target.h"
++#include "lldb/Target/ThreadSpec.h"
++#include "llvm/ADT/SmallString.h"
++#include "POSIXStopInfo.h"
++#include "NetBSDThread.h"
++#include "ProcessNetBSD.h"
++#include "ProcessPOSIXLog.h"
++#include "ProcessMonitor.h"
++#include "RegisterContextPOSIXProcessMonitor_x86.h"
++#include "Plugins/Process/Utility/RegisterContextNetBSD_x86_64.h"
++#include "Plugins/Process/Utility/UnwindLLDB.h"
++
++using namespace lldb;
++using namespace lldb_private;
++
++NetBSDThread::NetBSDThread(Process &process, lldb::tid_t tid)
++    : Thread(process, tid),
++      m_frame_ap (),
++      m_breakpoint (),
++      m_thread_name_valid (false),
++      m_thread_name (),
++      m_posix_thread(NULL)
++{
++    Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_THREAD));
++    if (log && log->GetMask().Test(POSIX_LOG_VERBOSE))
++        log->Printf ("NetBSDThread::%s (tid = %" PRIi64 ")", __FUNCTION__, tid);
++
++    // Set the current watchpoints for this thread.
++    Target &target = GetProcess()->GetTarget();
++    const WatchpointList &wp_list = target.GetWatchpointList();
++    size_t wp_size = wp_list.GetSize();
++
++    for (uint32_t wp_idx = 0; wp_idx < wp_size; wp_idx++)
++    {
++        lldb::WatchpointSP wp = wp_list.GetByIndex(wp_idx);
++        if (wp.get() && wp->IsEnabled())
++        {
++            // This watchpoint as been enabled; obviously this "new" thread
++            // has been created since that watchpoint was enabled.  Since
++            // the POSIXBreakpointProtocol has yet to be initialized, its
++            // m_watchpoints_initialized member will be FALSE.  Attempting to
++            // read the debug status register to determine if a watchpoint
++            // has been hit would result in the zeroing of that register.
++            // Since the active debug registers would have been cloned when
++            // this thread was created, simply force the m_watchpoints_initized
++            // member to TRUE and avoid resetting dr6 and dr7.
++            GetPOSIXBreakpointProtocol()->ForceWatchpointsInitialized();
++        }
++    }
++}
++
++NetBSDThread::~NetBSDThread()
++{
++    DestroyThread();
++}
++
++ProcessMonitor &
++NetBSDThread::GetMonitor()
++{
++    ProcessSP base = GetProcess();
++    ProcessNetBSD &process = static_cast<ProcessNetBSD&>(*base);
++    return process.GetMonitor();
++}
++
++void
++NetBSDThread::RefreshStateAfterStop()
++{
++    // Invalidate all registers in our register context. We don't set "force" to
++    // true because the stop reply packet might have had some register values
++    // that were expedited and these will already be copied into the register
++    // context by the time this function gets called. The KDPRegisterContext
++    // class has been made smart enough to detect when it needs to invalidate
++    // which registers are valid by putting hooks in the register read and 
++    // register supply functions where they check the process stop ID and do
++    // the right thing.
++    //if (StateIsStoppedState(GetState())
++    {
++        const bool force = false;
++        GetRegisterContext()->InvalidateIfNeeded (force);
++    }
++}
++
++const char *
++NetBSDThread::GetInfo()
++{
++    return NULL;
++}
++
++void
++NetBSDThread::SetName (const char *name)
++{
++    m_thread_name_valid = (name && name[0]);
++    if (m_thread_name_valid)
++        m_thread_name.assign (name);
++    else
++        m_thread_name.clear();
++}
++
++const char *
++NetBSDThread::GetName ()
++{
++    if (!m_thread_name_valid)
++    {
++        llvm::SmallString<32> thread_name;
++        HostNativeThread::GetName(/*GetID()*/ ::pthread_self(), thread_name);
++        m_thread_name = thread_name.c_str();
++        m_thread_name_valid = true;
++    }
++
++    if (m_thread_name.empty())
++        return NULL;
++    return m_thread_name.c_str();
++}
++
++lldb::RegisterContextSP
++NetBSDThread::GetRegisterContext()
++{
++    if (!m_reg_context_sp)
++    {
++        m_posix_thread = NULL;
++
++        RegisterInfoInterface *reg_interface = NULL;
++        const ArchSpec &target_arch = GetProcess()->GetTarget().GetArchitecture();
++
++        assert(target_arch.GetTriple().getOS() == llvm::Triple::NetBSD);
++        switch (target_arch.GetMachine())
++        {
++            case llvm::Triple::x86_64:
++                reg_interface = new RegisterContextNetBSD_x86_64(target_arch);
++                break;
++            default:
++                llvm_unreachable("CPU not supported");
++        }
++
++        switch (target_arch.GetMachine())
++        {
++            case llvm::Triple::x86_64:
++                {
++                    RegisterContextPOSIXProcessMonitor_x86_64 *reg_ctx = new RegisterContextPOSIXProcessMonitor_x86_64(*this, 0, reg_interface);
++                    m_posix_thread = reg_ctx;
++                    m_reg_context_sp.reset(reg_ctx);
++                    break;
++                }
++            default:
++                break;
++        }
++    }
++    return m_reg_context_sp;
++}
++
++lldb::RegisterContextSP
++NetBSDThread::CreateRegisterContextForFrame(lldb_private::StackFrame *frame)
++{
++    lldb::RegisterContextSP reg_ctx_sp;
++    uint32_t concrete_frame_idx = 0;
++
++    Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_THREAD));
++    if (log && log->GetMask().Test(POSIX_LOG_VERBOSE))
++        log->Printf ("NetBSDThread::%s ()", __FUNCTION__);
++
++    if (frame)
++        concrete_frame_idx = frame->GetConcreteFrameIndex();
++
++    if (concrete_frame_idx == 0)
++        reg_ctx_sp = GetRegisterContext();
++    else
++    {
++        assert(GetUnwinder());
++        reg_ctx_sp = GetUnwinder()->CreateRegisterContextForFrame(frame);
++    }
++
++    return reg_ctx_sp;
++}
++
++lldb::addr_t
++NetBSDThread::GetThreadPointer ()
++{
++    ProcessMonitor &monitor = GetMonitor();
++    addr_t addr;
++    if (monitor.ReadThreadPointer (GetID(), addr))
++        return addr;
++    else
++        return LLDB_INVALID_ADDRESS;
++}
++
++bool
++NetBSDThread::CalculateStopInfo()
++{
++    SetStopInfo (m_stop_info_sp);
++    return true;
++}
++
++Unwind *
++NetBSDThread::GetUnwinder()
++{
++    if (m_unwinder_ap.get() == NULL)
++        m_unwinder_ap.reset(new UnwindLLDB(*this));
++
++    return m_unwinder_ap.get();
++}
++
++void
++NetBSDThread::DidStop()
++{
++    // Don't set the thread state to stopped unless we really stopped.
++}
++
++void
++NetBSDThread::WillResume(lldb::StateType resume_state)
++{
++    Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_THREAD));
++    if (log)
++        log->Printf("tid %lu resume_state = %s", GetID(),
++                    lldb_private::StateAsCString(resume_state));
++    ProcessSP process_sp(GetProcess());
++    ProcessNetBSD *process = static_cast<ProcessNetBSD *>(process_sp.get());
++    int signo = GetResumeSignal();
++    bool signo_valid = process->GetUnixSignals()->SignalIsValid(signo);
++
++    switch (resume_state)
++    {
++    case eStateSuspended:
++    case eStateStopped:
++        process->m_suspend_tids.push_back(GetID());
++        break;
++    case eStateRunning:
++        process->m_run_tids.push_back(GetID());
++        if (signo_valid)
++            process->m_resume_signo = signo;
++        break;
++    case eStateStepping:
++        process->m_step_tids.push_back(GetID());
++        if (signo_valid)
++            process->m_resume_signo = signo;
++        break; 
++    default:
++        break;
++    }
++}
++
++bool
++NetBSDThread::Resume()
++{
++    lldb::StateType resume_state = GetResumeState();
++    ProcessMonitor &monitor = GetMonitor();
++    bool status;
++
++    Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_THREAD));
++    if (log)
++        log->Printf ("NetBSDThread::%s (), resume_state = %s", __FUNCTION__,
++                         StateAsCString(resume_state));
++
++    switch (resume_state)
++    {
++    default:
++        assert(false && "Unexpected state for resume!");
++        status = false;
++        break;
++
++    case lldb::eStateRunning:
++        SetState(resume_state);
++        status = monitor.Resume(GetID(), GetResumeSignal());
++        break;
++
++    case lldb::eStateStepping:
++        SetState(resume_state);
++        status = monitor.SingleStep(GetID(), GetResumeSignal());
++        break;
++    case lldb::eStateStopped:
++    case lldb::eStateSuspended:
++        status = true;
++        break;
++    }
++
++    return status;
++}
++
++void
++NetBSDThread::Notify(const ProcessMessage &message)
++{
++    Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_THREAD));
++    if (log)
++        log->Printf ("NetBSDThread::%s () message kind = '%s' for tid %" PRIu64,
++                     __FUNCTION__, message.PrintKind(), GetID());
++
++    switch (message.GetKind())
++    {
++    default:
++        assert(false && "Unexpected message kind!");
++        break;
++
++    case ProcessMessage::eExitMessage:
++        // Nothing to be done.
++        break;
++
++    case ProcessMessage::eLimboMessage:
++        LimboNotify(message);
++        break;
++
++    case ProcessMessage::eSignalMessage:
++        SignalNotify(message);
++        break;
++
++    case ProcessMessage::eSignalDeliveredMessage:
++        SignalDeliveredNotify(message);
++        break;
++
++    case ProcessMessage::eTraceMessage:
++        TraceNotify(message);
++        break;
++
++    case ProcessMessage::eBreakpointMessage:
++        BreakNotify(message);
++        break;
++
++    case ProcessMessage::eWatchpointMessage:
++        WatchNotify(message);
++        break;
++
++    case ProcessMessage::eCrashMessage:
++        CrashNotify(message);
++        break;
++
++    case ProcessMessage::eExecMessage:
++        ExecNotify(message);
++        break;
++    }
++}
++
++bool
++NetBSDThread::EnableHardwareWatchpoint(Watchpoint *wp)
++{
++    bool wp_set = false;
++    if (wp)
++    {
++        addr_t wp_addr = wp->GetLoadAddress();
++        size_t wp_size = wp->GetByteSize();
++        bool wp_read = wp->WatchpointRead();
++        bool wp_write = wp->WatchpointWrite();
++        uint32_t wp_hw_index = wp->GetHardwareIndex();
++        POSIXBreakpointProtocol* reg_ctx = GetPOSIXBreakpointProtocol();
++        if (reg_ctx)
++            wp_set = reg_ctx->SetHardwareWatchpointWithIndex(wp_addr, wp_size,
++                                                             wp_read, wp_write,
++                                                             wp_hw_index);
++    }
++    return wp_set;
++}
++
++bool
++NetBSDThread::DisableHardwareWatchpoint(Watchpoint *wp)
++{
++    bool result = false;
++    if (wp)
++    {
++        lldb::RegisterContextSP reg_ctx_sp = GetRegisterContext();
++        if (reg_ctx_sp.get())
++            result = reg_ctx_sp->ClearHardwareWatchpoint(wp->GetHardwareIndex());
++    }
++    return result;
++}
++
++uint32_t
++NetBSDThread::NumSupportedHardwareWatchpoints()
++{
++    lldb::RegisterContextSP reg_ctx_sp = GetRegisterContext();
++    if (reg_ctx_sp.get())
++        return reg_ctx_sp->NumSupportedHardwareWatchpoints();
++    return 0;
++}
++
++uint32_t
++NetBSDThread::FindVacantWatchpointIndex()
++{
++    uint32_t hw_index = LLDB_INVALID_INDEX32;
++    uint32_t num_hw_wps = NumSupportedHardwareWatchpoints();
++    uint32_t wp_idx;
++    POSIXBreakpointProtocol* reg_ctx = GetPOSIXBreakpointProtocol();
++    if (reg_ctx)
++    {
++        for (wp_idx = 0; wp_idx < num_hw_wps; wp_idx++)
++        {
++            if (reg_ctx->IsWatchpointVacant(wp_idx))
++            {
++                hw_index = wp_idx;
++                break;
++            }
++        }
++    }
++    return hw_index;
++}
++
++void
++NetBSDThread::BreakNotify(const ProcessMessage &message)
++{
++    bool status;
++    Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_THREAD));
++
++    assert(GetRegisterContext());
++    status = GetPOSIXBreakpointProtocol()->UpdateAfterBreakpoint();
++    assert(status && "Breakpoint update failed!");
++
++    // With our register state restored, resolve the breakpoint object
++    // corresponding to our current PC.
++    assert(GetRegisterContext());
++    lldb::addr_t pc = GetRegisterContext()->GetPC();
++    if (log)
++        log->Printf ("NetBSDThread::%s () PC=0x%8.8" PRIx64, __FUNCTION__, pc);
++    lldb::BreakpointSiteSP bp_site(GetProcess()->GetBreakpointSiteList().FindByAddress(pc));
++
++    // If the breakpoint is for this thread, then we'll report the hit, but if it is for another thread,
++    // we create a stop reason with should_stop=false.  If there is no breakpoint location, then report
++    // an invalid stop reason. We don't need to worry about stepping over the breakpoint here, that will
++    // be taken care of when the thread resumes and notices that there's a breakpoint under the pc.
++    if (bp_site)
++    {
++        lldb::break_id_t bp_id = bp_site->GetID();
++        // If we have an operating system plug-in, we might have set a thread specific breakpoint using the
++        // operating system thread ID, so we can't make any assumptions about the thread ID so we must always
++        // report the breakpoint regardless of the thread.
++        if (bp_site->ValidForThisThread(this) || GetProcess()->GetOperatingSystem () != NULL)
++            SetStopInfo (StopInfo::CreateStopReasonWithBreakpointSiteID(*this, bp_id));
++        else
++        {
++            const bool should_stop = false;
++            SetStopInfo (StopInfo::CreateStopReasonWithBreakpointSiteID(*this, bp_id, should_stop));
++        }
++    }
++    else
++        SetStopInfo(StopInfoSP());
++}
++
++void
++NetBSDThread::WatchNotify(const ProcessMessage &message)
++{
++    Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_THREAD));
++
++    lldb::addr_t halt_addr = message.GetHWAddress();
++    if (log)
++        log->Printf ("NetBSDThread::%s () Hardware Watchpoint Address = 0x%8.8"
++                     PRIx64, __FUNCTION__, halt_addr);
++
++    POSIXBreakpointProtocol* reg_ctx = GetPOSIXBreakpointProtocol();
++    if (reg_ctx)
++    {
++        uint32_t num_hw_wps = reg_ctx->NumSupportedHardwareWatchpoints();
++        uint32_t wp_idx;
++        for (wp_idx = 0; wp_idx < num_hw_wps; wp_idx++)
++        {
++            if (reg_ctx->IsWatchpointHit(wp_idx))
++            {
++                // Clear the watchpoint hit here
++                reg_ctx->ClearWatchpointHits();
++                break;
++            }
++        }
++
++        if (wp_idx == num_hw_wps)
++            return;
++
++        Target &target = GetProcess()->GetTarget();
++        lldb::addr_t wp_monitor_addr = reg_ctx->GetWatchpointAddress(wp_idx);
++        const WatchpointList &wp_list = target.GetWatchpointList();
++        lldb::WatchpointSP wp_sp = wp_list.FindByAddress(wp_monitor_addr);
++
++        assert(wp_sp.get() && "No watchpoint found");
++        SetStopInfo (StopInfo::CreateStopReasonWithWatchpointID(*this,
++                                                                wp_sp->GetID()));
++    }
++}
++
++void
++NetBSDThread::TraceNotify(const ProcessMessage &message)
++{
++    Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_THREAD));
++
++    // Try to resolve the breakpoint object corresponding to the current PC.
++    assert(GetRegisterContext());
++    lldb::addr_t pc = GetRegisterContext()->GetPC();
++    if (log)
++        log->Printf ("NetBSDThread::%s () PC=0x%8.8" PRIx64, __FUNCTION__, pc);
++    lldb::BreakpointSiteSP bp_site(GetProcess()->GetBreakpointSiteList().FindByAddress(pc));
++
++    // If the current pc is a breakpoint site then set the StopInfo to Breakpoint.
++    // Otherwise, set the StopInfo to Watchpoint or Trace.
++    // If we have an operating system plug-in, we might have set a thread specific breakpoint using the
++    // operating system thread ID, so we can't make any assumptions about the thread ID so we must always
++    // report the breakpoint regardless of the thread.
++    if (bp_site && (bp_site->ValidForThisThread(this) || GetProcess()->GetOperatingSystem () != NULL))
++        SetStopInfo(StopInfo::CreateStopReasonWithBreakpointSiteID(*this, bp_site->GetID()));
++    else
++    {
++        POSIXBreakpointProtocol* reg_ctx = GetPOSIXBreakpointProtocol();
++        if (reg_ctx)
++        {
++            uint32_t num_hw_wps = reg_ctx->NumSupportedHardwareWatchpoints();
++            uint32_t wp_idx;
++            for (wp_idx = 0; wp_idx < num_hw_wps; wp_idx++)
++            {
++                if (reg_ctx->IsWatchpointHit(wp_idx))
++                {
++                    WatchNotify(message);
++                    return;
++                }
++            }
++        }
++        SetStopInfo (StopInfo::CreateStopReasonToTrace(*this));
++    }
++}
++
++void
++NetBSDThread::LimboNotify(const ProcessMessage &message)
++{
++    SetStopInfo (lldb::StopInfoSP(new POSIXLimboStopInfo(*this)));
++}
++
++void
++NetBSDThread::SignalNotify(const ProcessMessage &message)
++{
++    int signo = message.GetSignal();
++    SetStopInfo (StopInfo::CreateStopReasonWithSignal(*this, signo));
++}
++
++void
++NetBSDThread::SignalDeliveredNotify(const ProcessMessage &message)
++{
++    int signo = message.GetSignal();
++    SetStopInfo (StopInfo::CreateStopReasonWithSignal(*this, signo));
++}
++
++void
++NetBSDThread::CrashNotify(const ProcessMessage &message)
++{
++    // FIXME: Update stop reason as per bugzilla 14598
++    int signo = message.GetSignal();
++
++    assert(message.GetKind() == ProcessMessage::eCrashMessage);
++
++    Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_THREAD));
++    if (log)
++        log->Printf ("NetBSDThread::%s () signo = %i, reason = '%s'",
++                     __FUNCTION__, signo, message.PrintCrashReason());
++
++    SetStopInfo (lldb::StopInfoSP(new POSIXCrashStopInfo(*this, signo,
++                                                         message.GetCrashReason(),
++                                                         message.GetFaultAddress())));
++}
++
++unsigned
++NetBSDThread::GetRegisterIndexFromOffset(unsigned offset)
++{
++    unsigned reg = LLDB_INVALID_REGNUM;
++    ArchSpec arch = HostInfo::GetArchitecture();
++
++    switch (arch.GetMachine())
++    {
++    default:
++        llvm_unreachable("CPU type not supported!");
++        break;
++
++    case llvm::Triple::x86_64:
++        {
++            POSIXBreakpointProtocol* reg_ctx = GetPOSIXBreakpointProtocol();
++            reg = reg_ctx->GetRegisterIndexFromOffset(offset);
++        }
++        break;
++    }
++    return reg;
++}
++
++void
++NetBSDThread::ExecNotify(const ProcessMessage &message)
++{
++    SetStopInfo (StopInfo::CreateStopReasonWithExec(*this));
++}
++
++const char *
++NetBSDThread::GetRegisterName(unsigned reg)
++{
++    const char * name = nullptr;
++    ArchSpec arch = HostInfo::GetArchitecture();
++
++    switch (arch.GetMachine())
++    {
++    default:
++        assert(false && "CPU type not supported!");
++        break;
++
++    case llvm::Triple::x86_64:
++        name = GetRegisterContext()->GetRegisterName(reg);
++        break;
++    }
++    return name;
++}
++
++const char *
++NetBSDThread::GetRegisterNameFromOffset(unsigned offset)
++{
++    return GetRegisterName(GetRegisterIndexFromOffset(offset));
++}
diff --git a/lldb-git/patches/patch-source_Plugins_Process_NetBSD_NetBSDThread.h b/lldb-git/patches/patch-source_Plugins_Process_NetBSD_NetBSDThread.h
new file mode 100644
index 0000000..cdc72bb
--- /dev/null
+++ b/lldb-git/patches/patch-source_Plugins_Process_NetBSD_NetBSDThread.h
@@ -0,0 +1,147 @@
+$NetBSD$
+
+--- source/Plugins/Process/NetBSD/NetBSDThread.h.orig	2016-05-03 20:18:09.426252287 +0000
++++ source/Plugins/Process/NetBSD/NetBSDThread.h
+@@ -0,0 +1,142 @@
++//===-- NetBSDThread.h -----------------------------------------*- C++ -*-===//
++//
++//                     The LLVM Compiler Infrastructure
++//
++// This file is distributed under the University of Illinois Open Source
++// License. See LICENSE.TXT for details.
++//
++//===----------------------------------------------------------------------===//
++
++#ifndef liblldb_NetBSDThread_H_
++#define liblldb_NetBSDThread_H_
++
++// C++ Includes
++#include <memory>
++#include <string>
++
++// Other libraries and framework includes
++#include "lldb/Target/Thread.h"
++#include "RegisterContextPOSIX.h"
++
++class ProcessMessage;
++class ProcessMonitor;
++class POSIXBreakpointProtocol;
++
++//------------------------------------------------------------------------------
++// @class NetBSDThread
++// @brief Abstraction of a NetBSD thread.
++class NetBSDThread
++    : public lldb_private::Thread
++{
++public:
++
++    //------------------------------------------------------------------
++    // Constructors and destructors
++    //------------------------------------------------------------------
++    NetBSDThread(lldb_private::Process &process, lldb::tid_t tid);
++
++    virtual ~NetBSDThread();
++
++    // POSIXThread
++    void
++    RefreshStateAfterStop() override;
++
++    // This notifies the thread when a private stop occurs.
++    void
++    DidStop () override;
++
++    const char *
++    GetInfo() override;
++
++    void
++    SetName (const char *name) override;
++
++    const char *
++    GetName () override;
++
++    lldb::RegisterContextSP
++    GetRegisterContext() override;
++
++    lldb::RegisterContextSP
++    CreateRegisterContextForFrame (lldb_private::StackFrame *frame) override;
++
++    lldb::addr_t
++    GetThreadPointer () override;
++
++    //--------------------------------------------------------------------------
++    // These functions provide a mapping from the register offset
++    // back to the register index or name for use in debugging or log
++    // output.
++
++    unsigned
++    GetRegisterIndexFromOffset(unsigned offset);
++
++    const char *
++    GetRegisterName(unsigned reg);
++
++    const char *
++    GetRegisterNameFromOffset(unsigned offset);
++
++    //--------------------------------------------------------------------------
++    // These methods form a specialized interface to POSIX threads.
++    //
++    bool Resume();
++
++    void Notify(const ProcessMessage &message);
++
++    //--------------------------------------------------------------------------
++    // These methods provide an interface to watchpoints
++    //
++    bool EnableHardwareWatchpoint(lldb_private::Watchpoint *wp);
++
++    bool DisableHardwareWatchpoint(lldb_private::Watchpoint *wp);
++
++    uint32_t NumSupportedHardwareWatchpoints();
++
++    uint32_t FindVacantWatchpointIndex();
++
++protected:
++    POSIXBreakpointProtocol *
++    GetPOSIXBreakpointProtocol ()
++    {
++        if (!m_reg_context_sp)
++            m_reg_context_sp = GetRegisterContext();
++        return m_posix_thread;
++    }
++    
++    std::unique_ptr<lldb_private::StackFrame> m_frame_ap;
++
++    lldb::BreakpointSiteSP m_breakpoint;
++
++    bool m_thread_name_valid;
++    std::string m_thread_name;
++    POSIXBreakpointProtocol *m_posix_thread;
++
++    ProcessMonitor &
++    GetMonitor();
++
++    bool
++    CalculateStopInfo() override;
++
++    void BreakNotify(const ProcessMessage &message);
++    void WatchNotify(const ProcessMessage &message);
++    virtual void TraceNotify(const ProcessMessage &message);
++    void LimboNotify(const ProcessMessage &message);
++    void SignalNotify(const ProcessMessage &message);
++    void SignalDeliveredNotify(const ProcessMessage &message);
++    void CrashNotify(const ProcessMessage &message);
++    void ExitNotify(const ProcessMessage &message);
++    void ExecNotify(const ProcessMessage &message);
++
++    lldb_private::Unwind *
++    GetUnwinder() override;
++
++    //--------------------------------------------------------------------------
++    // NetBSDThread internal API.
++
++    // POSIXThread override
++    virtual void
++    WillResume(lldb::StateType resume_state) override;
++};
++
++#endif // #ifndef liblldb_NetBSDThread_H_
diff --git a/lldb-git/patches/patch-source_Plugins_Process_NetBSD_POSIXStopInfo.cpp b/lldb-git/patches/patch-source_Plugins_Process_NetBSD_POSIXStopInfo.cpp
new file mode 100644
index 0000000..fee5c89
--- /dev/null
+++ b/lldb-git/patches/patch-source_Plugins_Process_NetBSD_POSIXStopInfo.cpp
@@ -0,0 +1,97 @@
+$NetBSD$
+
+--- source/Plugins/Process/NetBSD/POSIXStopInfo.cpp.orig	2016-05-03 20:18:09.431983532 +0000
++++ source/Plugins/Process/NetBSD/POSIXStopInfo.cpp
+@@ -0,0 +1,92 @@
++//===-- POSIXStopInfo.cpp ---------------------------------------*- C++ -*-===//
++//
++//                     The LLVM Compiler Infrastructure
++//
++// This file is distributed under the University of Illinois Open Source
++// License. See LICENSE.TXT for details.
++//
++//===----------------------------------------------------------------------===//
++
++#include "POSIXStopInfo.h"
++
++using namespace lldb;
++using namespace lldb_private;
++
++
++//===----------------------------------------------------------------------===//
++// POSIXLimboStopInfo
++
++POSIXLimboStopInfo::~POSIXLimboStopInfo() { }
++
++lldb::StopReason
++POSIXLimboStopInfo::GetStopReason() const
++{
++    return lldb::eStopReasonThreadExiting;
++}
++
++const char *
++POSIXLimboStopInfo::GetDescription()
++{
++    return "thread exiting";
++}
++
++bool
++POSIXLimboStopInfo::ShouldStop(Event *event_ptr)
++{
++    return false;
++}
++
++bool
++POSIXLimboStopInfo::ShouldNotify(Event *event_ptr)
++{
++    return false;
++}
++
++//===----------------------------------------------------------------------===//
++// POSIXCrashStopInfo
++
++POSIXCrashStopInfo::POSIXCrashStopInfo(NetBSDThread &thread,
++                                       uint32_t status,
++                                       CrashReason reason,
++                                       lldb::addr_t fault_addr)
++    : POSIXStopInfo(thread, status)
++{
++    m_description = ::GetCrashReasonString(reason, fault_addr);
++}
++
++POSIXCrashStopInfo::~POSIXCrashStopInfo() { }
++
++lldb::StopReason
++POSIXCrashStopInfo::GetStopReason() const
++{
++    return lldb::eStopReasonException;
++}
++
++//===----------------------------------------------------------------------===//
++// POSIXNewThreadStopInfo
++
++POSIXNewThreadStopInfo::~POSIXNewThreadStopInfo() { }
++
++lldb::StopReason
++POSIXNewThreadStopInfo::GetStopReason() const
++{
++    return lldb::eStopReasonNone;
++}
++
++const char *
++POSIXNewThreadStopInfo::GetDescription()
++{
++    return "thread spawned";
++}
++
++bool
++POSIXNewThreadStopInfo::ShouldStop(Event *event_ptr)
++{
++    return false;
++}
++
++bool
++POSIXNewThreadStopInfo::ShouldNotify(Event *event_ptr)
++{
++    return false;
++}
diff --git a/lldb-git/patches/patch-source_Plugins_Process_NetBSD_POSIXStopInfo.h b/lldb-git/patches/patch-source_Plugins_Process_NetBSD_POSIXStopInfo.h
new file mode 100644
index 0000000..c455c5a
--- /dev/null
+++ b/lldb-git/patches/patch-source_Plugins_Process_NetBSD_POSIXStopInfo.h
@@ -0,0 +1,115 @@
+$NetBSD$
+
+--- source/Plugins/Process/NetBSD/POSIXStopInfo.h.orig	2016-05-03 20:18:09.437595209 +0000
++++ source/Plugins/Process/NetBSD/POSIXStopInfo.h
+@@ -0,0 +1,110 @@
++//===-- POSIXStopInfo.h -----------------------------------------*- C++ -*-===//
++//
++//                     The LLVM Compiler Infrastructure
++//
++// This file is distributed under the University of Illinois Open Source
++// License. See LICENSE.TXT for details.
++//
++//===----------------------------------------------------------------------===//
++
++#ifndef liblldb_POSIXStopInfo_H_
++#define liblldb_POSIXStopInfo_H_
++
++// C Includes
++// C++ Includes
++// Other libraries and framework includes
++// Project includes
++#include "lldb/Target/StopInfo.h"
++
++#include "CrashReason.h"
++#include "NetBSDThread.h"
++
++#include <string>
++
++//===----------------------------------------------------------------------===//
++/// @class POSIXStopInfo
++/// @brief Simple base class for all POSIX-specific StopInfo objects.
++///
++class POSIXStopInfo
++    : public lldb_private::StopInfo
++{
++public:
++    POSIXStopInfo(lldb_private::Thread &thread, uint32_t status)
++        : StopInfo(thread, status)
++        { }
++};
++
++//===----------------------------------------------------------------------===//
++/// @class POSIXLimboStopInfo
++/// @brief Represents the stop state of a process ready to exit.
++///
++class POSIXLimboStopInfo
++    : public POSIXStopInfo
++{
++public:
++    POSIXLimboStopInfo(NetBSDThread &thread)
++        : POSIXStopInfo(thread, 0)
++        { }
++
++    ~POSIXLimboStopInfo();
++
++    lldb::StopReason
++    GetStopReason() const;
++
++    const char *
++    GetDescription();
++
++    bool
++    ShouldStop(lldb_private::Event *event_ptr);
++
++    bool
++    ShouldNotify(lldb_private::Event *event_ptr);
++};
++
++
++//===----------------------------------------------------------------------===//
++/// @class POSIXCrashStopInfo
++/// @brief Represents the stop state of process that is ready to crash.
++///
++class POSIXCrashStopInfo
++    : public POSIXStopInfo
++{
++public:
++    POSIXCrashStopInfo(NetBSDThread &thread, uint32_t status,
++                       CrashReason reason,
++                       lldb::addr_t fault_addr);
++    ~POSIXCrashStopInfo();
++
++    lldb::StopReason
++    GetStopReason() const;
++};
++
++//===----------------------------------------------------------------------===//
++/// @class POSIXNewThreadStopInfo
++/// @brief Represents the stop state of process when a new thread is spawned.
++///
++
++class POSIXNewThreadStopInfo
++    : public POSIXStopInfo
++{
++public:
++    POSIXNewThreadStopInfo (NetBSDThread &thread)
++        : POSIXStopInfo (thread, 0)
++        { }
++
++    ~POSIXNewThreadStopInfo();
++
++    lldb::StopReason
++    GetStopReason() const;
++
++    const char *
++    GetDescription();
++
++    bool
++    ShouldStop(lldb_private::Event *event_ptr);
++
++    bool
++    ShouldNotify(lldb_private::Event *event_ptr);
++};
++
++#endif
diff --git a/lldb-git/patches/patch-source_Plugins_Process_NetBSD_ProcessMonitor.cpp b/lldb-git/patches/patch-source_Plugins_Process_NetBSD_ProcessMonitor.cpp
new file mode 100644
index 0000000..4b4f1c3
--- /dev/null
+++ b/lldb-git/patches/patch-source_Plugins_Process_NetBSD_ProcessMonitor.cpp
@@ -0,0 +1,1349 @@
+$NetBSD$
+
+--- source/Plugins/Process/NetBSD/ProcessMonitor.cpp.orig	2016-05-03 20:18:09.443684111 +0000
++++ source/Plugins/Process/NetBSD/ProcessMonitor.cpp
+@@ -0,0 +1,1344 @@
++//===-- ProcessMonitor.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 <poll.h>
++#include <string.h>
++#include <stdint.h>
++#include <unistd.h>
++#include <signal.h>
++#include <sys/ptrace.h>
++#include <sys/socket.h>
++#include <sys/types.h>
++#include <sys/wait.h>
++
++// C++ Includes
++// Other libraries and framework includes
++#include "lldb/Core/Error.h"
++#include "lldb/Core/RegisterValue.h"
++#include "lldb/Core/Scalar.h"
++#include "lldb/Host/Host.h"
++#include "lldb/Host/ThreadLauncher.h"
++#include "lldb/Target/Thread.h"
++#include "lldb/Target/RegisterContext.h"
++#include "lldb/Target/UnixSignals.h"
++#include "lldb/Utility/PseudoTerminal.h"
++
++#include "Plugins/Process/POSIX/CrashReason.h"
++#include "NetBSDThread.h"
++#include "ProcessNetBSD.h"
++#include "ProcessPOSIXLog.h"
++#include "ProcessMonitor.h"
++
++extern "C" {
++      extern char ** environ;
++ }
++
++using namespace lldb;
++using namespace lldb_private;
++
++// We disable the tracing of ptrace calls for integration builds to
++// avoid the additional indirection and checks.
++#ifndef LLDB_CONFIGURATION_BUILDANDINTEGRATION
++// Wrapper for ptrace to catch errors and log calls.
++
++const char *
++Get_PT_IO_OP(int op)
++{
++    switch (op) {
++        case PIOD_READ_D:  return "READ_D";
++        case PIOD_WRITE_D: return "WRITE_D";
++        case PIOD_READ_I:  return "READ_I";
++        case PIOD_WRITE_I: return "WRITE_I";
++        default:           return "Unknown op";
++    }
++}
++
++// Wrapper for ptrace to catch errors and log calls.
++// Note that ptrace sets errno on error because -1 is reserved as a valid result.
++extern long
++PtraceWrapper(int req, lldb::pid_t pid, void *addr, int data,
++              const char* reqName, const char* file, int line)
++{
++    long int result;
++
++    Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PTRACE));
++
++    if (log) {
++        log->Printf("ptrace(%s, %" PRIu64 ", %p, %x) called from file %s line %d",
++                    reqName, pid, addr, data, file, line);
++        if (req == PT_IO) {
++            struct ptrace_io_desc *pi = (struct ptrace_io_desc *) addr;
++            
++            log->Printf("PT_IO: op=%s offs=%zx size=%zu",
++                     Get_PT_IO_OP(pi->piod_op), (size_t)pi->piod_offs, pi->piod_len);
++        }
++    }
++
++    //PtraceDisplayBytes(req, data);
++
++    errno = 0;
++    result = ptrace(req, pid, (caddr_t) addr, data);
++
++    //PtraceDisplayBytes(req, data);
++
++    if (log && errno != 0)
++    {
++        const char* str;
++        switch (errno)
++        {
++        case ESRCH:  str = "ESRCH"; break;
++        case EINVAL: str = "EINVAL"; break;
++        case EBUSY:  str = "EBUSY"; break;
++        case EPERM:  str = "EPERM"; break;
++        default:     str = "<unknown>";
++        }
++        log->Printf("ptrace() failed; errno=%d (%s)", errno, str);
++    }
++
++    if (log) {
++#ifdef __amd64__
++        if (req == PT_GETREGS) {
++            struct reg *r = (struct reg *) addr;
++
++            log->Printf("PT_GETREGS: rip=0x%lx rsp=0x%lx rbp=0x%lx rax=0x%lx",
++                        r->regs[_REG_RIP], r->regs[_REG_RSP], r->regs[_REG_RBP], r->regs[_REG_RAX]);
++        }
++#endif
++    }
++     
++    return result;
++}
++
++// Wrapper for ptrace when logging is not required.
++// Sets errno to 0 prior to calling ptrace.
++extern long
++PtraceWrapper(int req, lldb::pid_t pid, void *addr, int data)
++{
++    long result = 0;
++    errno = 0;
++    result = ptrace(req, pid, (caddr_t)addr, data);
++    return result;
++}
++
++#define PTRACE(req, pid, addr, data) \
++    PtraceWrapper((req), (pid), (addr), (data), #req, __FILE__, __LINE__)
++#else
++    PtraceWrapper((req), (pid), (addr), (data))
++#endif
++
++//------------------------------------------------------------------------------
++// Static implementations of ProcessMonitor::ReadMemory and
++// ProcessMonitor::WriteMemory.  This enables mutual recursion between these
++// functions without needed to go thru the thread funnel.
++
++static size_t
++DoReadMemory(lldb::pid_t pid, lldb::addr_t vm_addr, void *buf, size_t size, 
++             Error &error)
++{
++    struct ptrace_io_desc pi_desc;
++
++    pi_desc.piod_op = PIOD_READ_D;
++    pi_desc.piod_offs = (void *)vm_addr;
++    pi_desc.piod_addr = buf;
++    pi_desc.piod_len = size;
++
++    if (PTRACE(PT_IO, pid, (caddr_t)&pi_desc, 0) < 0)
++        error.SetErrorToErrno();
++    return pi_desc.piod_len;
++}
++
++static size_t
++DoWriteMemory(lldb::pid_t pid, lldb::addr_t vm_addr, const void *buf, 
++              size_t size, Error &error)
++{
++    struct ptrace_io_desc pi_desc;
++
++    pi_desc.piod_op = PIOD_WRITE_D;
++    pi_desc.piod_offs = (void *)vm_addr;
++    pi_desc.piod_addr = (void *)buf;
++    pi_desc.piod_len = size;
++
++    if (PTRACE(PT_IO, pid, (caddr_t)&pi_desc, 0) < 0)
++        error.SetErrorToErrno();
++    return pi_desc.piod_len;
++}
++
++// Simple helper function to ensure flags are enabled on the given file
++// descriptor.
++static bool
++EnsureFDFlags(int fd, int flags, Error &error)
++{
++    int status;
++
++    if ((status = fcntl(fd, F_GETFL)) == -1)
++    {
++        error.SetErrorToErrno();
++        return false;
++    }
++
++    if (fcntl(fd, F_SETFL, status | flags) == -1)
++    {
++        error.SetErrorToErrno();
++        return false;
++    }
++
++    return true;
++}
++
++//------------------------------------------------------------------------------
++/// @class Operation
++/// @brief Represents a ProcessMonitor operation.
++///
++/// Under NetBSD, it is not possible to ptrace() from any other thread but the
++/// one that spawned or attached to the process from the start.  Therefore, when
++/// a ProcessMonitor is asked to deliver or change the state of an inferior
++/// process the operation must be "funneled" to a specific thread to perform the
++/// task.  The Operation class provides an abstract base for all services the
++/// ProcessMonitor must perform via the single virtual function Execute, thus
++/// encapsulating the code that needs to run in the privileged context.
++class Operation
++{
++public:
++    virtual ~Operation() {}
++    virtual void Execute(ProcessMonitor *monitor) = 0;
++};
++
++//------------------------------------------------------------------------------
++/// @class ReadOperation
++/// @brief Implements ProcessMonitor::ReadMemory.
++class ReadOperation : public Operation
++{
++public:
++    ReadOperation(lldb::addr_t addr, void *buff, size_t size,
++                  Error &error, size_t &result)
++        : m_addr(addr), m_buff(buff), m_size(size),
++          m_error(error), m_result(result)
++        { }
++
++    void Execute(ProcessMonitor *monitor);
++
++private:
++    lldb::addr_t m_addr;
++    void *m_buff;
++    size_t m_size;
++    Error &m_error;
++    size_t &m_result;
++};
++
++void
++ReadOperation::Execute(ProcessMonitor *monitor)
++{
++    lldb::pid_t pid = monitor->GetPID();
++
++    m_result = DoReadMemory(pid, m_addr, m_buff, m_size, m_error);
++}
++
++//------------------------------------------------------------------------------
++/// @class WriteOperation
++/// @brief Implements ProcessMonitor::WriteMemory.
++class WriteOperation : public Operation
++{
++public:
++    WriteOperation(lldb::addr_t addr, const void *buff, size_t size,
++                   Error &error, size_t &result)
++        : m_addr(addr), m_buff(buff), m_size(size),
++          m_error(error), m_result(result)
++        { }
++
++    void Execute(ProcessMonitor *monitor);
++
++private:
++    lldb::addr_t m_addr;
++    const void *m_buff;
++    size_t m_size;
++    Error &m_error;
++    size_t &m_result;
++};
++
++void
++WriteOperation::Execute(ProcessMonitor *monitor)
++{
++    lldb::pid_t pid = monitor->GetPID();
++
++    m_result = DoWriteMemory(pid, m_addr, m_buff, m_size, m_error);
++}
++
++//------------------------------------------------------------------------------
++/// @class ReadRegOperation
++/// @brief Implements ProcessMonitor::ReadRegisterValue.
++class ReadRegOperation : public Operation
++{
++public:
++    ReadRegOperation(lldb::tid_t tid, unsigned offset, unsigned size,
++                     RegisterValue &value, bool &result)
++        : m_tid(tid), m_offset(offset), m_size(size),
++          m_value(value), m_result(result)
++        { }
++
++    void Execute(ProcessMonitor *monitor);
++
++private:
++    lldb::tid_t m_tid;
++    unsigned m_offset;
++    unsigned m_size;
++    RegisterValue &m_value;
++    bool &m_result;
++};
++
++void
++ReadRegOperation::Execute(ProcessMonitor *monitor)
++{
++    struct reg regs;
++    int rc;
++
++    if ((rc = PTRACE(PT_GETREGS, m_tid, (caddr_t)&regs, 0)) < 0) {
++        m_result = false;
++    } else {
++        // 'struct reg' contains only 32- or 64-bit register values.  Punt on
++        // others.  Also, not all entries may be uintptr_t sized, such as 32-bit
++        // processes on powerpc64 (probably the same for i386 on amd64)
++        if (m_size == sizeof(uint32_t))
++            m_value = *(uint32_t *)(((caddr_t)&regs) + m_offset);
++        else if (m_size == sizeof(uint64_t))
++            m_value = *(uint64_t *)(((caddr_t)&regs) + m_offset);
++        else
++            memcpy((void *)&m_value, (((caddr_t)&regs) + m_offset), m_size);
++        m_result = true;
++    }
++}
++
++//------------------------------------------------------------------------------
++/// @class WriteRegOperation
++/// @brief Implements ProcessMonitor::WriteRegisterValue.
++class WriteRegOperation : public Operation
++{
++public:
++    WriteRegOperation(lldb::tid_t tid, unsigned offset,
++                      const RegisterValue &value, bool &result)
++        : m_tid(tid), m_offset(offset),
++          m_value(value), m_result(result)
++        { }
++
++    void Execute(ProcessMonitor *monitor);
++
++private:
++    lldb::tid_t m_tid;
++    unsigned m_offset;
++    const RegisterValue &m_value;
++    bool &m_result;
++};
++
++void
++WriteRegOperation::Execute(ProcessMonitor *monitor)
++{
++    struct reg regs;
++
++    if (PTRACE(PT_GETREGS, m_tid, (caddr_t)&regs, 0) < 0) {
++        m_result = false;
++        return;
++    }
++    *(uintptr_t *)(((caddr_t)&regs) + m_offset) = (uintptr_t)m_value.GetAsUInt64();
++    if (PTRACE(PT_SETREGS, m_tid, (caddr_t)&regs, 0) < 0)
++        m_result = false;
++    else
++        m_result = true;
++}
++
++//------------------------------------------------------------------------------
++/// @class ReadGPROperation
++/// @brief Implements ProcessMonitor::ReadGPR.
++class ReadGPROperation : public Operation
++{
++public:
++    ReadGPROperation(lldb::tid_t tid, void *buf, bool &result)
++        : m_tid(tid), m_buf(buf), m_result(result)
++        { }
++
++    void Execute(ProcessMonitor *monitor);
++
++private:
++    lldb::tid_t m_tid;
++    void *m_buf;
++    bool &m_result;
++};
++
++void
++ReadGPROperation::Execute(ProcessMonitor *monitor)
++{
++    int rc;
++
++    errno = 0;
++    rc = PTRACE(PT_GETREGS, m_tid, (caddr_t)m_buf, 0);
++    if (errno != 0)
++        m_result = false;
++    else
++        m_result = true;
++}
++
++//------------------------------------------------------------------------------
++/// @class ReadFPROperation
++/// @brief Implements ProcessMonitor::ReadFPR.
++class ReadFPROperation : public Operation
++{
++public:
++    ReadFPROperation(lldb::tid_t tid, void *buf, bool &result)
++        : m_tid(tid), m_buf(buf), m_result(result)
++        { }
++
++    void Execute(ProcessMonitor *monitor);
++
++private:
++    lldb::tid_t m_tid;
++    void *m_buf;
++    bool &m_result;
++};
++
++void
++ReadFPROperation::Execute(ProcessMonitor *monitor)
++{
++    if (PTRACE(PT_GETFPREGS, m_tid, (caddr_t)m_buf, 0) < 0)
++        m_result = false;
++    else
++        m_result = true;
++}
++
++//------------------------------------------------------------------------------
++/// @class WriteGPROperation
++/// @brief Implements ProcessMonitor::WriteGPR.
++class WriteGPROperation : public Operation
++{
++public:
++    WriteGPROperation(lldb::tid_t tid, void *buf, bool &result)
++        : m_tid(tid), m_buf(buf), m_result(result)
++        { }
++
++    void Execute(ProcessMonitor *monitor);
++
++private:
++    lldb::tid_t m_tid;
++    void *m_buf;
++    bool &m_result;
++};
++
++void
++WriteGPROperation::Execute(ProcessMonitor *monitor)
++{
++    if (PTRACE(PT_SETREGS, m_tid, (caddr_t)m_buf, 0) < 0)
++        m_result = false;
++    else
++        m_result = true;
++}
++
++//------------------------------------------------------------------------------
++/// @class WriteFPROperation
++/// @brief Implements ProcessMonitor::WriteFPR.
++class WriteFPROperation : public Operation
++{
++public:
++    WriteFPROperation(lldb::tid_t tid, void *buf, bool &result)
++        : m_tid(tid), m_buf(buf), m_result(result)
++        { }
++
++    void Execute(ProcessMonitor *monitor);
++
++private:
++    lldb::tid_t m_tid;
++    void *m_buf;
++    bool &m_result;
++};
++
++void
++WriteFPROperation::Execute(ProcessMonitor *monitor)
++{
++    if (PTRACE(PT_SETFPREGS, m_tid, (caddr_t)m_buf, 0) < 0)
++        m_result = false;
++    else
++        m_result = true;
++}
++
++//------------------------------------------------------------------------------
++/// @class ResumeOperation
++/// @brief Implements ProcessMonitor::Resume.
++class ResumeOperation : public Operation
++{
++public:
++    ResumeOperation(uint32_t signo, bool &result) :
++        m_signo(signo), m_result(result) { }
++
++    void Execute(ProcessMonitor *monitor);
++
++private:
++    uint32_t m_signo;
++    bool &m_result;
++};
++
++void
++ResumeOperation::Execute(ProcessMonitor *monitor)
++{
++    lldb::pid_t pid = monitor->GetPID();
++    int data = 0;
++
++    if (m_signo != LLDB_INVALID_SIGNAL_NUMBER)
++        data = m_signo;
++
++    if (PTRACE(PT_CONTINUE, pid, (caddr_t)1, data))
++    {
++        Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_PROCESS));
++
++        if (log)
++            log->Printf ("ResumeOperation (%"  PRIu64 ") failed: %s", pid, strerror(errno));
++        m_result = false;
++    }
++    else
++        m_result = true;
++}
++
++//------------------------------------------------------------------------------
++/// @class SingleStepOperation
++/// @brief Implements ProcessMonitor::SingleStep.
++class SingleStepOperation : public Operation
++{
++public:
++    SingleStepOperation(uint32_t signo, bool &result)
++        : m_signo(signo), m_result(result) { }
++
++    void Execute(ProcessMonitor *monitor);
++
++private:
++    uint32_t m_signo;
++    bool &m_result;
++};
++
++void
++SingleStepOperation::Execute(ProcessMonitor *monitor)
++{
++    lldb::pid_t pid = monitor->GetPID();
++    int data = 0;
++
++    if (m_signo != LLDB_INVALID_SIGNAL_NUMBER)
++        data = m_signo;
++
++    if (PTRACE(PT_STEP, pid, NULL, data))
++        m_result = false;
++    else
++        m_result = true;
++}
++
++//------------------------------------------------------------------------------
++/// @class LwpInfoOperation
++/// @brief Implements ProcessMonitor::GetLwpInfo.
++class LwpInfoOperation : public Operation
++{
++public:
++    LwpInfoOperation(lldb::tid_t tid, void *info, bool &result, int &ptrace_err)
++        : m_tid(tid), m_info(info), m_result(result), m_err(ptrace_err) { }
++
++    void Execute(ProcessMonitor *monitor);
++
++private:
++    lldb::tid_t m_tid;
++    void *m_info;
++    bool &m_result;
++    int &m_err;
++};
++
++void
++LwpInfoOperation::Execute(ProcessMonitor *monitor)
++{
++    struct ptrace_lwpinfo plwp;
++
++    if (PTRACE(PT_LWPINFO, m_tid, (caddr_t)&plwp, sizeof(plwp))) {
++        m_result = false;
++        m_err = errno;
++    } else {
++        memcpy(m_info, &plwp, sizeof(plwp));
++        m_result = true;
++    }
++}
++
++//------------------------------------------------------------------------------
++/// @class ThreadSuspendOperation
++/// @brief Implements ProcessMonitor::ThreadSuspend.
++class ThreadSuspendOperation : public Operation
++{
++public:
++    ThreadSuspendOperation(lldb::tid_t tid, bool suspend, bool &result)
++        : m_tid(tid), m_suspend(suspend), m_result(result) { }
++
++    void Execute(ProcessMonitor *monitor);
++
++private:
++    lldb::tid_t m_tid;
++    bool m_suspend;
++    bool &m_result;
++} ;
++
++//------------------------------------------------------------------------------
++/// @class EventMessageOperation
++/// @brief Implements ProcessMonitor::GetEventMessage.
++class EventMessageOperation : public Operation
++{
++public:
++    EventMessageOperation(lldb::tid_t tid, unsigned long *message, bool &result)
++        : m_tid(tid), m_message(message), m_result(result) { }
++
++    void Execute(ProcessMonitor *monitor);
++
++private:
++    lldb::tid_t m_tid;
++    unsigned long *m_message;
++    bool &m_result;
++};
++
++void
++EventMessageOperation::Execute(ProcessMonitor *monitor)
++{
++    struct ptrace_lwpinfo plwp;
++
++    if (PTRACE(PT_LWPINFO, m_tid, (caddr_t)&plwp, sizeof(plwp)))
++        m_result = false;
++    else
++        m_result = true;
++}
++
++//------------------------------------------------------------------------------
++/// @class KillOperation
++/// @brief Implements ProcessMonitor::Kill.
++class KillOperation : public Operation
++{
++public:
++    KillOperation(bool &result) : m_result(result) { }
++
++    void Execute(ProcessMonitor *monitor);
++
++private:
++    bool &m_result;
++};
++
++void
++KillOperation::Execute(ProcessMonitor *monitor)
++{
++    lldb::pid_t pid = monitor->GetPID();
++
++    if (PTRACE(PT_KILL, pid, NULL, 0))
++        m_result = false;
++    else
++        m_result = true;
++}
++
++//------------------------------------------------------------------------------
++/// @class DetachOperation
++/// @brief Implements ProcessMonitor::Detach.
++class DetachOperation : public Operation
++{
++public:
++    DetachOperation(Error &result) : m_error(result) { }
++
++    void Execute(ProcessMonitor *monitor);
++
++private:
++    Error &m_error;
++};
++
++void
++DetachOperation::Execute(ProcessMonitor *monitor)
++{
++    lldb::pid_t pid = monitor->GetPID();
++
++    if (PTRACE(PT_DETACH, pid, NULL, 0) < 0)
++        m_error.SetErrorToErrno();
++  
++}
++
++ProcessMonitor::OperationArgs::OperationArgs(ProcessMonitor *monitor)
++    : m_monitor(monitor)
++{
++    sem_init(&m_semaphore, 0, 0);
++}
++
++ProcessMonitor::OperationArgs::~OperationArgs()
++{
++    sem_destroy(&m_semaphore);
++}
++
++ProcessMonitor::LaunchArgs::LaunchArgs(ProcessMonitor *monitor,
++                                       lldb_private::Module *module,
++                                       char const **argv,
++                                       char const **envp,
++                                       const FileSpec &stdin_file_spec,
++                                       const FileSpec &stdout_file_spec,
++                                       const FileSpec &stderr_file_spec,
++                                       const FileSpec &working_dir)
++    : OperationArgs(monitor),
++      m_module(module),
++      m_argv(argv),
++      m_envp(envp),
++      m_stdin_file_spec(stdin_file_spec),
++      m_stdout_file_spec(stdout_file_spec),
++      m_stderr_file_spec(stderr_file_spec),
++      m_working_dir(working_dir) { }
++
++ProcessMonitor::LaunchArgs::~LaunchArgs()
++{ }
++
++ProcessMonitor::AttachArgs::AttachArgs(ProcessMonitor *monitor,
++                                       lldb::pid_t pid)
++    : OperationArgs(monitor), m_pid(pid) { }
++
++ProcessMonitor::AttachArgs::~AttachArgs()
++{ }
++
++//------------------------------------------------------------------------------
++/// The basic design of the ProcessMonitor is built around two threads.
++///
++/// One thread (@see SignalThread) simply blocks on a call to waitpid() looking
++/// for changes in the debugee state.  When a change is detected a
++/// ProcessMessage is sent to the associated ProcessNetBSD instance.  This thread
++/// "drives" state changes in the debugger.
++///
++/// The second thread (@see OperationThread) is responsible for two things 1)
++/// launching or attaching to the inferior process, and then 2) servicing
++/// operations such as register reads/writes, stepping, etc.  See the comments
++/// on the Operation class for more info as to why this is needed.
++ProcessMonitor::ProcessMonitor(ProcessNetBSD *process,
++                               Module *module,
++                               const char *argv[],
++                               const char *envp[],
++                               const FileSpec &stdin_file_spec,
++                               const FileSpec &stdout_file_spec,
++                               const FileSpec &stderr_file_spec,
++                               const FileSpec &working_dir,
++                               const lldb_private::ProcessLaunchInfo & /* launch_info */,
++                               lldb_private::Error &error)
++    : m_process(static_cast<ProcessNetBSD *>(process)),
++      m_pid(LLDB_INVALID_PROCESS_ID),
++      m_terminal_fd(-1),
++      m_operation(0)
++{
++    std::unique_ptr<LaunchArgs> args(new LaunchArgs(this, module, argv, envp,
++                                                    stdin_file_spec,
++                                                    stdout_file_spec,
++                                                    stderr_file_spec,
++                                                    working_dir));
++    
++
++    sem_init(&m_operation_pending, 0, 0);
++    sem_init(&m_operation_done, 0, 0);
++
++    StartLaunchOpThread(args.get(), error);
++    if (!error.Success())
++        return;
++
++WAIT_AGAIN:
++    // Wait for the operation thread to initialize.
++    if (sem_wait(&args->m_semaphore))
++    {
++        if (errno == EINTR)
++            goto WAIT_AGAIN;
++        else
++        {
++            error.SetErrorToErrno();
++            return;
++        }
++    }
++
++    // Check that the launch was a success.
++    if (!args->m_error.Success())
++    {
++        StopOpThread();
++        error = args->m_error;
++        return;
++    }
++
++    // Finally, start monitoring the child process for change in state.
++    m_monitor_thread = Host::StartMonitoringChildProcess(
++        ProcessMonitor::MonitorCallback, this, GetPID(), true);
++    if (!m_monitor_thread.IsJoinable())
++    {
++        error.SetErrorToGenericError();
++        error.SetErrorString("Process launch failed.");
++        return;
++    }
++}
++
++ProcessMonitor::ProcessMonitor(ProcessNetBSD *process,
++                               lldb::pid_t pid,
++                               lldb_private::Error &error)
++    : m_process(static_cast<ProcessNetBSD *>(process)),
++      m_pid(pid),
++      m_terminal_fd(-1),
++      m_operation(0)
++{
++    sem_init(&m_operation_pending, 0, 0);
++    sem_init(&m_operation_done, 0, 0);
++
++
++    std::unique_ptr<AttachArgs> args(new AttachArgs(this, pid));
++
++    StartAttachOpThread(args.get(), error);
++    if (!error.Success())
++        return;
++
++WAIT_AGAIN:
++    // Wait for the operation thread to initialize.
++    if (sem_wait(&args->m_semaphore))
++    {
++        if (errno == EINTR)
++            goto WAIT_AGAIN;
++        else
++        {
++            error.SetErrorToErrno();
++            return;
++        }
++    }
++
++    // Check that the attach was a success.
++    if (!args->m_error.Success())
++    {
++        StopOpThread();
++        error = args->m_error;
++        return;
++    }
++
++    // Finally, start monitoring the child process for change in state.
++    m_monitor_thread = Host::StartMonitoringChildProcess(
++        ProcessMonitor::MonitorCallback, this, GetPID(), true);
++    if (!m_monitor_thread.IsJoinable())
++    {
++        error.SetErrorToGenericError();
++        error.SetErrorString("Process attach failed.");
++        return;
++    }
++}
++
++ProcessMonitor::~ProcessMonitor()
++{
++    StopMonitor();
++}
++
++//------------------------------------------------------------------------------
++// Thread setup and tear down.
++void
++ProcessMonitor::StartLaunchOpThread(LaunchArgs *args, Error &error)
++{
++    static const char *g_thread_name = "lldb.process.netbsd.operation";
++
++    if (m_operation_thread.IsJoinable())
++        return;
++
++    m_operation_thread = ThreadLauncher::LaunchThread(g_thread_name, LaunchOpThread, args, &error);
++}
++
++void *
++ProcessMonitor::LaunchOpThread(void *arg)
++{
++    LaunchArgs *args = static_cast<LaunchArgs*>(arg);
++
++    if (!Launch(args)) {
++        sem_post(&args->m_semaphore);
++        return NULL;
++    }
++
++    ServeOperation(args);
++    return NULL;
++}
++
++bool
++ProcessMonitor::Launch(LaunchArgs *args)
++{
++    ProcessMonitor *monitor = args->m_monitor;
++    ProcessNetBSD &process = monitor->GetProcess();
++    const char **argv = args->m_argv;
++    const char **envp = args->m_envp;
++    const FileSpec &stdin_file_spec = args->m_stdin_file_spec;
++    const FileSpec &stdout_file_spec = args->m_stdout_file_spec;
++    const FileSpec &stderr_file_spec = args->m_stderr_file_spec;
++    const FileSpec &working_dir = args->m_working_dir;
++
++    lldb_utility::PseudoTerminal terminal;
++    const size_t err_len = 1024;
++    char err_str[err_len];
++    ::pid_t pid;
++
++    // Propagate the environment if one is not supplied.
++    if (envp == NULL || envp[0] == NULL)
++        envp = const_cast<const char **>(environ);
++
++    if ((pid = terminal.Fork(err_str, err_len)) == -1)
++    {
++        args->m_error.SetErrorToGenericError();
++        args->m_error.SetErrorString("Process fork failed.");
++        goto FINISH;
++    }
++
++    // Recognized child exit status codes.
++    enum {
++        ePtraceFailed = 1,
++        eDupStdinFailed,
++        eDupStdoutFailed,
++        eDupStderrFailed,
++        eChdirFailed,
++        eExecFailed,
++        eSetGidFailed
++    };
++
++    // Child process.
++    if (pid == 0)
++    {
++        // Trace this process.
++        if (PTRACE(PT_TRACE_ME, 0, NULL, 0) < 0)
++            exit(ePtraceFailed);
++
++        // terminal has already dupped the tty descriptors to stdin/out/err.
++        // This closes original fd from which they were copied (and avoids
++        // leaking descriptors to the debugged process.
++        terminal.CloseSlaveFileDescriptor();
++
++        // Do not inherit setgid powers.
++        if (setgid(getgid()) != 0)
++            exit(eSetGidFailed);
++
++        // Let us have our own process group.
++        setpgid(0, 0);
++
++        // Dup file descriptors if needed.
++        //
++        // FIXME: If two or more of the paths are the same we needlessly open
++        // the same file multiple times.
++        if (stdin_file_spec)
++            if (!DupDescriptor(stdin_file_spec, STDIN_FILENO, O_RDONLY))
++                exit(eDupStdinFailed);
++
++        if (stdout_file_spec)
++            if (!DupDescriptor(stdout_file_spec, STDOUT_FILENO, O_WRONLY | O_CREAT))
++                exit(eDupStdoutFailed);
++
++        if (stderr_file_spec)
++            if (!DupDescriptor(stderr_file_spec, STDERR_FILENO, O_WRONLY | O_CREAT))
++                exit(eDupStderrFailed);
++
++        // Change working directory
++        if (working_dir && 0 != ::chdir(working_dir.GetCString()))
++            exit(eChdirFailed);
++
++        // Execute.  We should never return.
++        execve(argv[0],
++               const_cast<char *const *>(argv),
++               const_cast<char *const *>(envp));
++        exit(eExecFailed);
++    }
++
++    // Wait for the child process to to trap on its call to execve.
++    ::pid_t wpid;
++    int status;
++    if ((wpid = waitpid(pid, &status, 0)) < 0)
++    {
++        args->m_error.SetErrorToErrno();
++        goto FINISH;
++    }
++    else if (WIFEXITED(status))
++    {
++        // open, dup or execve likely failed for some reason.
++        args->m_error.SetErrorToGenericError();
++        switch (WEXITSTATUS(status))
++        {
++            case ePtraceFailed:
++                args->m_error.SetErrorString("Child ptrace failed.");
++                break;
++            case eDupStdinFailed:
++                args->m_error.SetErrorString("Child open stdin failed.");
++                break;
++            case eDupStdoutFailed:
++                args->m_error.SetErrorString("Child open stdout failed.");
++                break;
++            case eDupStderrFailed:
++                args->m_error.SetErrorString("Child open stderr failed.");
++                break;
++            case eChdirFailed:
++                args->m_error.SetErrorString("Child failed to set working directory.");
++                break;
++            case eExecFailed:
++                args->m_error.SetErrorString("Child exec failed.");
++                break;
++            case eSetGidFailed:
++                args->m_error.SetErrorString("Child setgid failed.");
++                break;
++            default:
++                args->m_error.SetErrorString("Child returned unknown exit status.");
++                break;
++        }
++        goto FINISH;
++    }
++    assert(WIFSTOPPED(status) && wpid == (::pid_t)pid &&
++           "Could not sync with inferior process.");
++
++#ifdef notyet
++    // Have the child raise an event on exit.  This is used to keep the child in
++    // limbo until it is destroyed.
++    if (PTRACE(PTRACE_SETOPTIONS, pid, NULL, PTRACE_O_TRACEEXIT) < 0)
++    {
++        args->m_error.SetErrorToErrno();
++        goto FINISH;
++    }
++#endif
++    // Release the master terminal descriptor and pass it off to the
++    // ProcessMonitor instance.  Similarly stash the inferior pid.
++    monitor->m_terminal_fd = terminal.ReleaseMasterFileDescriptor();
++    monitor->m_pid = pid;
++
++    // Set the terminal fd to be in non blocking mode (it simplifies the
++    // implementation of ProcessNetBSD::GetSTDOUT to have a non-blocking
++    // descriptor to read from).
++    if (!EnsureFDFlags(monitor->m_terminal_fd, O_NONBLOCK, args->m_error))
++        goto FINISH;
++
++    process.SendMessage(ProcessMessage::Attach(pid));
++
++FINISH:
++    return args->m_error.Success();
++}
++
++void
++ProcessMonitor::StartAttachOpThread(AttachArgs *args, lldb_private::Error &error)
++{
++    static const char *g_thread_name = "lldb.process.netbsd.operation";
++
++    if (m_operation_thread.IsJoinable())
++        return;
++
++    m_operation_thread = ThreadLauncher::LaunchThread(g_thread_name, AttachOpThread, args, &error);
++}
++
++void *
++ProcessMonitor::AttachOpThread(void *arg)
++{
++    AttachArgs *args = static_cast<AttachArgs*>(arg);
++
++    Attach(args);
++
++    ServeOperation(args);
++    return NULL;
++}
++
++void
++ProcessMonitor::Attach(AttachArgs *args)
++{
++    lldb::pid_t pid = args->m_pid;
++
++    ProcessMonitor *monitor = args->m_monitor;
++    ProcessNetBSD &process = monitor->GetProcess();
++
++    if (pid <= 1)
++    {
++        args->m_error.SetErrorToGenericError();
++        args->m_error.SetErrorString("Attaching to process 1 is not allowed.");
++        return;
++    }
++
++    // Attach to the requested process.
++    if (PTRACE(PT_ATTACH, pid, NULL, 0) < 0)
++    {
++        args->m_error.SetErrorToErrno();
++        return;
++    }
++
++    int status;
++    if ((status = waitpid(pid, NULL, 0)) < 0)
++    {
++        args->m_error.SetErrorToErrno();
++        return;
++    }
++
++    process.SendMessage(ProcessMessage::Attach(pid));
++}
++
++bool
++ProcessMonitor::MonitorCallback(void *callback_baton,
++                                lldb::pid_t pid,
++                                bool exited,
++                                int signal,
++                                int status)
++{
++    ProcessMessage message;
++    ProcessMonitor *monitor = static_cast<ProcessMonitor*>(callback_baton);
++    ProcessNetBSD *process = monitor->m_process;
++    assert(process);
++    bool stop_monitoring;
++    struct ptrace_lwpinfo plwp;
++    int ptrace_err;
++
++    Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_PROCESS));
++
++    if (exited)
++    {
++        if (log)
++            log->Printf ("ProcessMonitor::%s() got exit signal, tid = %"  PRIu64, __FUNCTION__, pid);
++        message = ProcessMessage::Exit(pid, status);
++        process->SendMessage(message);
++        return pid == process->GetID();
++    }
++
++    if (!monitor->GetLwpInfo(pid, &plwp, ptrace_err))
++    {
++        stop_monitoring = true; // pid is gone.  Bail.
++    }
++
++    return stop_monitoring;
++}
++
++void
++ProcessMonitor::ServeOperation(OperationArgs *args)
++{
++    ProcessMonitor *monitor = args->m_monitor;
++
++    // We are finised with the arguments and are ready to go.  Sync with the
++    // parent thread and start serving operations on the inferior.
++    sem_post(&args->m_semaphore);
++
++    for (;;)
++    {
++        // wait for next pending operation
++        sem_wait(&monitor->m_operation_pending);
++
++        monitor->m_operation->Execute(monitor);
++
++        // notify calling thread that operation is complete
++        sem_post(&monitor->m_operation_done);
++    }
++}
++
++void
++ProcessMonitor::DoOperation(Operation *op)
++{
++    Mutex::Locker lock(m_operation_mutex);
++
++    m_operation = op;
++
++    // notify operation thread that an operation is ready to be processed
++    sem_post(&m_operation_pending);
++
++    // wait for operation to complete
++    sem_wait(&m_operation_done);
++}
++
++size_t
++ProcessMonitor::ReadMemory(lldb::addr_t vm_addr, void *buf, size_t size,
++                           Error &error)
++{
++    size_t result;
++    ReadOperation op(vm_addr, buf, size, error, result);
++    DoOperation(&op);
++    return result;
++}
++
++size_t
++ProcessMonitor::WriteMemory(lldb::addr_t vm_addr, const void *buf, size_t size,
++                            lldb_private::Error &error)
++{
++    size_t result;
++    WriteOperation op(vm_addr, buf, size, error, result);
++    DoOperation(&op);
++    return result;
++}
++
++bool
++ProcessMonitor::ReadRegisterValue(lldb::tid_t tid, unsigned offset, const char* reg_name,
++                                  unsigned size, RegisterValue &value)
++{
++    bool result;
++    ReadRegOperation op(tid, offset, size, value, result);
++    DoOperation(&op);
++    return result;
++}
++
++bool
++ProcessMonitor::WriteRegisterValue(lldb::tid_t tid, unsigned offset,
++                                   const char* reg_name, const RegisterValue &value)
++{
++    bool result;
++    WriteRegOperation op(tid, offset, value, result);
++    DoOperation(&op);
++    return result;
++}
++
++bool
++ProcessMonitor::ReadGPR(lldb::tid_t tid, void *buf, size_t buf_size)
++{
++    bool result;
++    ReadGPROperation op(tid, buf, result);
++    DoOperation(&op);
++    return result;
++}
++
++bool
++ProcessMonitor::ReadFPR(lldb::tid_t tid, void *buf, size_t buf_size)
++{
++    bool result;
++    ReadFPROperation op(tid, buf, result);
++    DoOperation(&op);
++    return result;
++}
++
++bool
++ProcessMonitor::ReadRegisterSet(lldb::tid_t tid, void *buf, size_t buf_size, unsigned int regset)
++{
++    return false;
++}
++
++bool
++ProcessMonitor::WriteGPR(lldb::tid_t tid, void *buf, size_t buf_size)
++{
++    bool result;
++    WriteGPROperation op(tid, buf, result);
++    DoOperation(&op);
++    return result;
++}
++
++bool
++ProcessMonitor::WriteFPR(lldb::tid_t tid, void *buf, size_t buf_size)
++{
++    bool result;
++    WriteFPROperation op(tid, buf, result);
++    DoOperation(&op);
++    return result;
++}
++
++bool
++ProcessMonitor::WriteRegisterSet(lldb::tid_t tid, void *buf, size_t buf_size, unsigned int regset)
++{
++    return false;
++}
++
++bool
++ProcessMonitor::ReadThreadPointer(lldb::tid_t tid, lldb::addr_t &value)
++{
++    return false;
++}
++
++bool
++ProcessMonitor::SingleStep(lldb::tid_t unused, uint32_t signo)
++{
++    bool result;
++    SingleStepOperation op(signo, result);
++    DoOperation(&op);
++    return result;
++}
++
++bool
++ProcessMonitor::Kill()
++{
++    bool result;
++    KillOperation op(result);
++    DoOperation(&op);
++    return result;
++}
++
++bool
++ProcessMonitor::GetLwpInfo(lldb::tid_t tid, void *lwpinfo, int &ptrace_err)
++{
++    bool result;
++    LwpInfoOperation op(tid, lwpinfo, result, ptrace_err);
++    DoOperation(&op);
++    return result;
++}
++
++bool
++ProcessMonitor::GetEventMessage(lldb::tid_t tid, unsigned long *message)
++{
++    bool result;
++    EventMessageOperation op(tid, message, result);
++    DoOperation(&op);
++    return result;
++}
++
++lldb_private::Error
++ProcessMonitor::Detach(lldb::tid_t tid)
++{
++    lldb_private::Error error;
++    if (tid != LLDB_INVALID_THREAD_ID)
++    {
++        DetachOperation op(error);
++        DoOperation(&op);
++    }
++    return error;
++}    
++
++bool
++ProcessMonitor::DupDescriptor(const FileSpec &file_spec, int fd, int flags)
++{
++    int target_fd = open(file_spec.GetCString(), flags, 0666);
++
++    if (target_fd == -1)
++        return false;
++
++    if (dup2(target_fd, fd) == -1)
++        return false;
++
++    return (close(target_fd) == -1) ? false : true;
++}
++
++void
++ProcessMonitor::StopMonitoringChildProcess()
++{
++    if (m_monitor_thread.IsJoinable())
++    {
++        m_monitor_thread.Cancel();
++        m_monitor_thread.Join(nullptr);
++        m_monitor_thread.Reset();
++    }
++}
++
++void
++ProcessMonitor::StopMonitor()
++{
++    StopMonitoringChildProcess();
++    StopOpThread();
++    sem_destroy(&m_operation_pending);
++    sem_destroy(&m_operation_done);
++    if (m_terminal_fd >= 0) {
++        close(m_terminal_fd);
++        m_terminal_fd = -1;
++    }
++}
++
++// FIXME: On Linux, when a new thread is created, we receive to notifications,
++// (1) a SIGTRAP|PTRACE_EVENT_CLONE from the main process thread with the
++// child thread id as additional information, and (2) a SIGSTOP|SI_USER from
++// the new child thread indicating that it has is stopped because we attached.
++// We have no guarantee of the order in which these arrive, but we need both
++// before we are ready to proceed.  We currently keep a list of threads which
++// have sent the initial SIGSTOP|SI_USER event.  Then when we receive the
++// SIGTRAP|PTRACE_EVENT_CLONE notification, if the initial stop has not occurred
++// we call ProcessMonitor::WaitForInitialTIDStop() to wait for it.
++//
++// Right now, the above logic is in ProcessPOSIX, so we need a definition of
++// this function in the NetBSD ProcessMonitor implementation even if it isn't
++// logically needed.
++//
++// We really should figure out what actually happens on NetBSD and move the
++// Linux-specific logic out of ProcessPOSIX as needed.
++
++bool
++ProcessMonitor::WaitForInitialTIDStop(lldb::tid_t tid)
++{
++    return true;
++}
++
++void
++ProcessMonitor::StopOpThread()
++{
++    if (!m_operation_thread.IsJoinable())
++        return;
++
++    m_operation_thread.Cancel();
++    m_operation_thread.Join(nullptr);
++    m_operation_thread.Reset();
++}
diff --git a/lldb-git/patches/patch-source_Plugins_Process_NetBSD_ProcessMonitor.h b/lldb-git/patches/patch-source_Plugins_Process_NetBSD_ProcessMonitor.h
new file mode 100644
index 0000000..f887f0a
--- /dev/null
+++ b/lldb-git/patches/patch-source_Plugins_Process_NetBSD_ProcessMonitor.h
@@ -0,0 +1,308 @@
+$NetBSD$
+
+--- source/Plugins/Process/NetBSD/ProcessMonitor.h.orig	2016-05-03 20:18:09.450107065 +0000
++++ source/Plugins/Process/NetBSD/ProcessMonitor.h
+@@ -0,0 +1,303 @@
++//===-- ProcessMonitor.h -------------------------------------- -*- C++ -*-===//
++//
++//                     The LLVM Compiler Infrastructure
++//
++// This file is distributed under the University of Illinois Open Source
++// License. See LICENSE.TXT for details.
++//
++//===----------------------------------------------------------------------===//
++
++#ifndef liblldb_ProcessMonitor_H_
++#define liblldb_ProcessMonitor_H_
++
++// C Includes
++#include <semaphore.h>
++#include <signal.h>
++
++// C++ Includes
++// Other libraries and framework includes
++#include "lldb/lldb-types.h"
++#include "lldb/Host/FileSpec.h"
++#include "lldb/Host/HostThread.h"
++#include "lldb/Host/Mutex.h"
++
++namespace lldb_private
++{
++class Error;
++class Module;
++class Scalar;
++} // End lldb_private namespace.
++
++class ProcessNetBSD;
++class Operation;
++
++/// @class ProcessMonitor
++/// @brief Manages communication with the inferior (debugee) process.
++///
++/// Upon construction, this class prepares and launches an inferior process for
++/// debugging.
++///
++/// Changes in the inferior process state are propagated to the associated
++/// ProcessNetBSD instance by calling ProcessNetBSD::SendMessage with the
++/// appropriate ProcessMessage events.
++///
++/// A purposely minimal set of operations are provided to interrogate and change
++/// the inferior process state.
++class ProcessMonitor
++{
++public:
++
++    /// Launches an inferior process ready for debugging.  Forms the
++    /// implementation of Process::DoLaunch.
++    ProcessMonitor(ProcessNetBSD *process,
++                   lldb_private::Module *module,
++                   char const *argv[],
++                   char const *envp[],
++                   const lldb_private::FileSpec &stdin_file_spec,
++                   const lldb_private::FileSpec &stdout_file_spec,
++                   const lldb_private::FileSpec &stderr_file_spec,
++                   const lldb_private::FileSpec &working_dir,
++                   const lldb_private::ProcessLaunchInfo &launch_info,
++                   lldb_private::Error &error);
++
++    ProcessMonitor(ProcessNetBSD *process,
++                   lldb::pid_t pid,
++                   lldb_private::Error &error);
++
++    ~ProcessMonitor();
++
++    /// Provides the process number of debugee.
++    lldb::pid_t
++    GetPID() const { return m_pid; }
++
++    /// Returns the process associated with this ProcessMonitor.
++    ProcessNetBSD &
++    GetProcess() { return *m_process; }
++
++    /// Returns a file descriptor to the controlling terminal of the inferior
++    /// process.
++    ///
++    /// Reads from this file descriptor yield both the standard output and
++    /// standard error of this debugee.  Even if stderr and stdout were
++    /// redirected on launch it may still happen that data is available on this
++    /// descriptor (if the inferior process opens /dev/tty, for example). This descriptor is
++    /// closed after a call to StopMonitor().
++    ///
++    /// If this monitor was attached to an existing process this method returns
++    /// -1.
++    int
++    GetTerminalFD() const { return m_terminal_fd; }
++
++    /// Reads @p size bytes from address @vm_adder in the inferior process
++    /// address space.
++    ///
++    /// This method is provided to implement Process::DoReadMemory.
++    size_t
++    ReadMemory(lldb::addr_t vm_addr, void *buf, size_t size,
++               lldb_private::Error &error);
++
++    /// Writes @p size bytes from address @p vm_adder in the inferior process
++    /// address space.
++    ///
++    /// This method is provided to implement Process::DoWriteMemory.
++    size_t
++    WriteMemory(lldb::addr_t vm_addr, const void *buf, size_t size,
++                lldb_private::Error &error);
++
++    /// Reads the contents from the register identified by the given (architecture
++    /// dependent) offset.
++    ///
++    /// This method is provided for use by RegisterContextNetBSD derivatives.
++    bool
++    ReadRegisterValue(lldb::tid_t tid, unsigned offset, const char *reg_name,
++                      unsigned size, lldb_private::RegisterValue &value);
++
++    /// Writes the given value to the register identified by the given
++    /// (architecture dependent) offset.
++    ///
++    /// This method is provided for use by RegisterContextNetBSD derivatives.
++    bool
++    WriteRegisterValue(lldb::tid_t tid, unsigned offset, const char *reg_name,
++                       const lldb_private::RegisterValue &value);
++
++    /// Reads all general purpose registers into the specified buffer.
++    bool
++    ReadGPR(lldb::tid_t tid, void *buf, size_t buf_size);
++
++    /// Reads all floating point registers into the specified buffer.
++    bool
++    ReadFPR(lldb::tid_t tid, void *buf, size_t buf_size);
++
++    /// Reads the specified register set into the specified buffer.
++    ///
++    /// This method is provided for use by RegisterContextNetBSD derivatives.
++    bool
++    ReadRegisterSet(lldb::tid_t tid, void *buf, size_t buf_size, unsigned int regset);
++
++    /// Writes all general purpose registers into the specified buffer.
++    bool
++    WriteGPR(lldb::tid_t tid, void *buf, size_t buf_size);
++
++    /// Writes all floating point registers into the specified buffer.
++    bool
++    WriteFPR(lldb::tid_t tid, void *buf, size_t buf_size);
++
++    /// Writes the specified register set into the specified buffer.
++    ///
++    /// This method is provided for use by RegisterContextNetBSD derivatives.
++    bool
++    WriteRegisterSet(lldb::tid_t tid, void *buf, size_t buf_size, unsigned int regset);
++
++    /// Reads the value of the thread-specific pointer for a given thread ID.
++    bool
++    ReadThreadPointer(lldb::tid_t tid, lldb::addr_t &value);
++
++    /// Returns current thread IDs in process
++    size_t
++    GetCurrentThreadIDs(std::vector<lldb::tid_t> &thread_ids);
++
++    /// Writes a ptrace_lwpinfo structure corresponding to the given thread ID
++    /// to the memory region pointed to by @p lwpinfo.
++    bool
++    GetLwpInfo(lldb::tid_t tid, void *lwpinfo, int &error_no);
++
++    /// Suspends or unsuspends a thread prior to process resume or step.
++    bool
++    ThreadSuspend(lldb::tid_t tid, bool suspend);
++
++    /// Writes the raw event message code (vis-a-vis PTRACE_GETEVENTMSG)
++    /// corresponding to the given thread IDto the memory pointed to by @p
++    /// message.
++    bool
++    GetEventMessage(lldb::tid_t tid, unsigned long *message);
++
++    /// Resumes the process.  If @p signo is anything but
++    /// LLDB_INVALID_SIGNAL_NUMBER, deliver that signal to the process.
++    bool
++    Resume(lldb::tid_t unused, uint32_t signo);
++
++    /// Single steps the process.  If @p signo is anything but
++    /// LLDB_INVALID_SIGNAL_NUMBER, deliver that signal to the process.
++    bool
++    SingleStep(lldb::tid_t unused, uint32_t signo);
++
++    /// Terminate the traced process.
++    bool
++    Kill();
++
++    lldb_private::Error
++    Detach(lldb::tid_t tid);
++
++    void
++    StopMonitor();
++
++    // Waits for the initial stop message from a new thread.
++    bool
++    WaitForInitialTIDStop(lldb::tid_t tid);
++
++private:
++    ProcessNetBSD *m_process;
++
++    lldb_private::HostThread m_operation_thread;
++    lldb_private::HostThread m_monitor_thread;
++    lldb::pid_t m_pid;
++
++    int m_terminal_fd;
++
++    // current operation which must be executed on the privileged thread
++    Operation *m_operation;
++    lldb_private::Mutex m_operation_mutex;
++
++    // semaphores notified when Operation is ready to be processed and when
++    // the operation is complete.
++    sem_t m_operation_pending;
++    sem_t m_operation_done;
++
++    struct OperationArgs
++    {
++        OperationArgs(ProcessMonitor *monitor);
++
++        ~OperationArgs();
++
++        ProcessMonitor *m_monitor;      // The monitor performing the attach.
++        sem_t m_semaphore;              // Posted to once operation complete.
++        lldb_private::Error m_error;    // Set if process operation failed.
++    };
++
++    /// @class LauchArgs
++    ///
++    /// @brief Simple structure to pass data to the thread responsible for
++    /// launching a child process.
++    struct LaunchArgs : OperationArgs
++    {
++        LaunchArgs(ProcessMonitor *monitor,
++                   lldb_private::Module *module,
++                   char const **argv,
++                   char const **envp,
++                   const lldb_private::FileSpec &stdin_file_spec,
++                   const lldb_private::FileSpec &stdout_file_spec,
++                   const lldb_private::FileSpec &stderr_file_spec,
++                   const lldb_private::FileSpec &working_dir);
++
++        ~LaunchArgs();
++
++        lldb_private::Module *m_module;                  // The executable image to launch.
++        char const **m_argv;                             // Process arguments.
++        char const **m_envp;                             // Process environment.
++        const lldb_private::FileSpec m_stdin_file_spec;  // Redirect stdin or empty.
++        const lldb_private::FileSpec m_stdout_file_spec; // Redirect stdout or empty.
++        const lldb_private::FileSpec m_stderr_file_spec; // Redirect stderr or empty.
++        const lldb_private::FileSpec m_working_dir;      // Working directory or empty.
++    };
++
++    void
++    StartLaunchOpThread(LaunchArgs *args, lldb_private::Error &error);
++
++    static void *
++    LaunchOpThread(void *arg);
++
++    static bool
++    Launch(LaunchArgs *args);
++
++    struct AttachArgs : OperationArgs
++    {
++        AttachArgs(ProcessMonitor *monitor,
++                   lldb::pid_t pid);
++
++        ~AttachArgs();
++
++        lldb::pid_t m_pid;              // pid of the process to be attached.
++    };
++
++    void
++    StartAttachOpThread(AttachArgs *args, lldb_private::Error &error);
++
++    static void *
++    AttachOpThread(void *args);
++
++    static void
++    Attach(AttachArgs *args);
++
++    static void
++    ServeOperation(OperationArgs *args);
++
++    static bool
++    DupDescriptor(const lldb_private::FileSpec &file_spec, int fd, int flags);
++
++    static bool
++    MonitorCallback(void *callback_baton,
++                    lldb::pid_t pid, bool exited, int signal, int status);
++
++    void
++    DoOperation(Operation *op);
++
++    /// Stops the child monitor thread.
++    void
++    StopMonitoringChildProcess();
++
++    /// Stops the operation thread used to attach/launch a process.
++    void
++    StopOpThread();
++};
++
++#endif // #ifndef liblldb_ProcessMonitor_H_
diff --git a/lldb-git/patches/patch-source_Plugins_Process_NetBSD_ProcessNetBSD.cpp b/lldb-git/patches/patch-source_Plugins_Process_NetBSD_ProcessNetBSD.cpp
new file mode 100644
index 0000000..2b48e6c
--- /dev/null
+++ b/lldb-git/patches/patch-source_Plugins_Process_NetBSD_ProcessNetBSD.cpp
@@ -0,0 +1,941 @@
+$NetBSD$
+
+--- source/Plugins/Process/NetBSD/ProcessNetBSD.cpp.orig	2016-05-03 20:18:09.456132900 +0000
++++ source/Plugins/Process/NetBSD/ProcessNetBSD.cpp
+@@ -0,0 +1,936 @@
++//===-- ProcessNetBSD.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 "ProcessNetBSD.h"
++#include "ProcessPOSIXLog.h"
++#include "Plugins/Process/Utility/InferiorCallPOSIX.h"
++#include "Plugins/Process/Utility/NetBSDSignals.h"
++#include "ProcessMonitor.h"
++#include "NetBSDThread.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&
++    GetNetBSDSignals ()
++    {
++        static UnixSignalsSP s_netbsd_signals_sp (new NetBSDSignals ());
++        return s_netbsd_signals_sp;
++    }
++}
++
++//------------------------------------------------------------------------------
++// Static functions.
++
++lldb::ProcessSP
++ProcessNetBSD::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 ProcessNetBSD (target_sp, listener_sp, GetNetBSDSignals()));
++    return process_sp;
++}
++
++void
++ProcessNetBSD::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
++ProcessNetBSD::GetPluginNameStatic()
++{
++    static ConstString g_name("netbsd");
++    return g_name;
++}
++
++const char *
++ProcessNetBSD::GetPluginDescriptionStatic()
++{
++    return "Process plugin for NetBSD";
++}
++
++//------------------------------------------------------------------------------
++// ProcessInterface protocol.
++
++lldb_private::ConstString
++ProcessNetBSD::GetPluginName()
++{
++    return GetPluginNameStatic();
++}
++
++uint32_t
++ProcessNetBSD::GetPluginVersion()
++{
++    return 1;
++}
++
++void
++ProcessNetBSD::Terminate()
++{
++}
++
++Error
++ProcessNetBSD::DoDetach(bool keep_stopped)
++{
++    Error error;
++    if (keep_stopped)
++    {
++        error.SetErrorString("Detaching with keep_stopped true is not currently supported on NetBSD.");
++        return error;
++    }
++
++    error = m_monitor->Detach(GetID());
++
++    if (error.Success())
++        SetPrivateState(eStateDetached);
++
++    return error;
++}
++
++bool
++ProcessNetBSD::UpdateThreadList(ThreadList &old_thread_list, ThreadList &new_thread_list)
++{
++    Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_PROCESS));
++    if (log)
++        log->Printf("ProcessNetBSD::%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 NetBSDThread(*this, tid));
++            if (log)
++                log->Printf("ProcessNetBSD::%s new tid = %" PRIu64, __FUNCTION__, tid);
++        }
++        else
++        {
++            if (log)
++                log->Printf("ProcessNetBSD::%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("ProcessNetBSD::%s remove tid", __FUNCTION__);
++        }
++    }
++
++    return true;
++}
++
++Error
++ProcessNetBSD::WillResume()
++{
++    m_resume_signo = 0;
++    m_suspend_tids.clear();
++    m_run_tids.clear();
++    m_step_tids.clear();
++    return Process::WillResume();
++}
++
++void
++ProcessNetBSD::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 NetBSD");
++        break;
++
++    case ProcessMessage::eExecMessage:
++        SetPrivateState(eStateStopped);
++        break;
++    }
++
++    m_message_queue.push(message);
++}
++
++//------------------------------------------------------------------------------
++// Constructors and destructors.
++
++ProcessNetBSD::ProcessNetBSD(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 (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();
++}
++
++ProcessNetBSD::~ProcessNetBSD()
++{
++    delete m_monitor;
++}
++
++//------------------------------------------------------------------------------
++// Process protocol.
++void
++ProcessNetBSD::Finalize()
++{
++  Process::Finalize();
++
++  if (m_monitor)
++    m_monitor->StopMonitor();
++}
++
++bool
++ProcessNetBSD::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
++ProcessNetBSD::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 ("ProcessNetBSD::%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
++ProcessNetBSD::WillLaunch(Module* module)
++{
++    Error error;
++    return error;
++}
++
++FileSpec
++ProcessNetBSD::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
++ProcessNetBSD::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.
++        int stdio = fcntl(terminal, F_DUPFD_CLOEXEC, 0);
++        if (stdio == -1) {
++            error.SetErrorToErrno();
++            return error;
++        }
++        SetSTDIOFileDescriptor(stdio);
++    }
++
++    SetID(m_monitor->GetPID());
++    return error;
++}
++
++void
++ProcessNetBSD::DidLaunch()
++{
++}
++
++addr_t
++ProcessNetBSD::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
++ProcessNetBSD::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
++ProcessNetBSD::DoSignal(int signal)
++{
++    Error error;
++
++    if (kill(GetID(), signal))
++        error.SetErrorToErrno();
++
++    return error;
++}
++
++Error
++ProcessNetBSD::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
++ProcessNetBSD::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
++ProcessNetBSD::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
++ProcessNetBSD::WaitingForInitialStop(lldb::tid_t stop_tid)
++{
++    return (m_seen_initial_stop.find(stop_tid) == m_seen_initial_stop.end());
++}
++
++NetBSDThread *
++ProcessNetBSD::CreateNewNetBSDThread(lldb_private::Process &process, lldb::tid_t tid)
++{
++    return new NetBSDThread(process, tid);
++}
++
++void
++ProcessNetBSD::RefreshStateAfterStop()
++{
++    Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_PROCESS));
++    if (log && log->GetMask().Test(POSIX_LOG_VERBOSE))
++        log->Printf ("ProcessNetBSD::%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 ("ProcessNetBSD::%s(), message_queue size = %d, pid = %" PRIi64, __FUNCTION__, (int)m_message_queue.size(), tid);
++
++        m_thread_list.RefreshStateAfterStop();
++
++        NetBSDThread *thread = static_cast<NetBSDThread*>(
++            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 ("ProcessNetBSD::%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
++ProcessNetBSD::IsAlive()
++{
++    StateType state = GetPrivateState();
++    return state != eStateDetached
++        && state != eStateExited
++        && state != eStateInvalid
++        && state != eStateUnloaded;
++}
++
++size_t
++ProcessNetBSD::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
++ProcessNetBSD::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
++ProcessNetBSD::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
++ProcessNetBSD::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
++ProcessNetBSD::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::x86_64:
++        opcode = g_i386_opcode;
++        opcode_size = sizeof(g_i386_opcode);
++        break;
++    }
++
++    bp_site->SetTrapOpcode(opcode, opcode_size);
++    return opcode_size;
++}
++
++Error
++ProcessNetBSD::EnableBreakpointSite(BreakpointSite *bp_site)
++{
++    return EnableSoftwareBreakpoint(bp_site);
++}
++
++Error
++ProcessNetBSD::DisableBreakpointSite(BreakpointSite *bp_site)
++{
++    return DisableSoftwareBreakpoint(bp_site);
++}
++
++Error
++ProcessNetBSD::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 ("ProcessNetBSD::EnableWatchpoint(watchID = %" PRIu64 ")",
++                         watchID);
++        if (wp->IsEnabled())
++        {
++            if (log)
++                log->Printf("ProcessNetBSD::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());
++        NetBSDThread *thread = static_cast<NetBSDThread*>(
++                               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<NetBSDThread*>(
++                         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
++ProcessNetBSD::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("ProcessNetBSD::DisableWatchpoint(watchID = %" PRIu64 ")",
++                        watchID);
++        if (!wp->IsEnabled())
++        {
++            if (log)
++                log->Printf("ProcessNetBSD::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)
++            {
++                NetBSDThread *thread = static_cast<NetBSDThread*>(
++                                      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
++ProcessNetBSD::GetWatchpointSupportInfo(uint32_t &num)
++{
++    Error error;
++    Mutex::Locker lock(m_thread_list.GetMutex());
++    NetBSDThread *thread = static_cast<NetBSDThread*>(
++                          m_thread_list.GetThreadAtIndex(0, false).get());
++    if (thread)
++        num = thread->NumSupportedHardwareWatchpoints();
++    else
++        error.SetErrorString("Process does not exist.");
++    return error;
++}
++
++Error
++ProcessNetBSD::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
++ProcessNetBSD::UpdateThreadListIfNeeded()
++{
++    Mutex::Locker lock(m_thread_list.GetMutex());
++    // Do not allow recursive updates.
++    return m_thread_list.GetSize(false);
++}
++
++ByteOrder
++ProcessNetBSD::GetByteOrder() const
++{
++    // FIXME: We should be able to extract this value directly.  See comment in
++    // ProcessNetBSD().
++    return m_byte_order;
++}
++
++size_t
++ProcessNetBSD::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
++ProcessNetBSD::HasExited()
++{
++    switch (GetPrivateState())
++    {
++    default:
++        break;
++
++    case eStateDetached:
++    case eStateExited:
++        return true;
++    }
++
++    return false;
++}
++
++bool
++ProcessNetBSD::IsStopped()
++{
++    switch (GetPrivateState())
++    {
++    default:
++        break;
++
++    case eStateStopped:
++    case eStateCrashed:
++    case eStateSuspended:
++        return true;
++    }
++
++    return false;
++}
++
++bool
++ProcessNetBSD::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)
++    {
++        NetBSDThread *thread = static_cast<NetBSDThread*>(
++            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
++ProcessNetBSD::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 ProcessNetBSD?");
++    return DataBufferSP ();
++}
diff --git a/lldb-git/patches/patch-source_Plugins_Process_NetBSD_ProcessNetBSD.h b/lldb-git/patches/patch-source_Plugins_Process_NetBSD_ProcessNetBSD.h
new file mode 100644
index 0000000..f2807e8
--- /dev/null
+++ b/lldb-git/patches/patch-source_Plugins_Process_NetBSD_ProcessNetBSD.h
@@ -0,0 +1,254 @@
+$NetBSD$
+
+--- source/Plugins/Process/NetBSD/ProcessNetBSD.h.orig	2016-05-03 20:18:09.462107752 +0000
++++ source/Plugins/Process/NetBSD/ProcessNetBSD.h
+@@ -0,0 +1,249 @@
++//===-- ProcessNetBSD.h ------------------------------------------*- C++ -*-===//
++//
++//                     The LLVM Compiler Infrastructure
++//
++// This file is distributed under the University of Illinois Open Source
++// License. See LICENSE.TXT for details.
++//
++//===----------------------------------------------------------------------===//
++
++#ifndef liblldb_ProcessNetBSD_H_
++#define liblldb_ProcessNetBSD_H_
++
++// C Includes
++
++// C++ Includes
++#include <set>
++#include <queue>
++
++// Other libraries and framework includes
++#include "lldb/Target/Process.h"
++#include "lldb/Target/ThreadList.h"
++#include "ProcessMessage.h"
++#include "ProcessNetBSD.h"
++
++class ProcessMonitor;
++class NetBSDThread;
++
++class ProcessNetBSD :
++    public lldb_private::Process
++{
++
++public:
++    //------------------------------------------------------------------
++    // Static functions.
++    //------------------------------------------------------------------
++    static lldb::ProcessSP
++    CreateInstance(lldb::TargetSP target_sp,
++                   lldb::ListenerSP listener_sp,
++                   const lldb_private::FileSpec *crash_file_path);
++
++    static void
++    Initialize();
++
++    static void
++    Terminate();
++
++    static lldb_private::ConstString
++    GetPluginNameStatic();
++
++    static const char *
++    GetPluginDescriptionStatic();
++
++    //------------------------------------------------------------------
++    // Constructors and destructors
++    //------------------------------------------------------------------
++    ProcessNetBSD(lldb::TargetSP target_sp,
++                   lldb::ListenerSP listener_sp,
++                   lldb::UnixSignalsSP &unix_signals_sp);
++
++    ~ProcessNetBSD();
++
++    virtual lldb_private::Error
++    WillResume() override;
++
++    //------------------------------------------------------------------
++    // PluginInterface protocol
++    //------------------------------------------------------------------
++    virtual lldb_private::ConstString
++    GetPluginName() override;
++
++    virtual uint32_t
++    GetPluginVersion() override;
++
++public:
++    //------------------------------------------------------------------
++    // Process protocol.
++    //------------------------------------------------------------------
++    void
++    Finalize() override;
++
++    bool
++    CanDebug(lldb::TargetSP target_sp, bool plugin_specified_by_name) override;
++
++    lldb_private::Error
++    WillLaunch(lldb_private::Module *module) override;
++
++    lldb_private::Error
++    DoAttachToProcessWithID (lldb::pid_t pid, const lldb_private::ProcessAttachInfo &attach_info) override;
++
++    lldb_private::Error
++    DoLaunch (lldb_private::Module *exe_module,
++              lldb_private::ProcessLaunchInfo &launch_info) override;
++
++    void
++    DidLaunch() override;
++
++    lldb_private::Error
++    DoResume() override;
++
++    lldb_private::Error
++    DoHalt(bool &caused_stop) override;
++
++    lldb_private::Error
++    DoDetach(bool keep_stopped) override;
++
++    lldb_private::Error
++    DoSignal(int signal) override;
++
++    lldb_private::Error
++    DoDestroy() override;
++
++    void
++    DoDidExec() override;
++
++    void
++    RefreshStateAfterStop() override;
++
++    bool
++    IsAlive() override;
++
++    size_t
++    DoReadMemory(lldb::addr_t vm_addr,
++                 void *buf,
++                 size_t size,
++                 lldb_private::Error &error) override;
++
++    size_t
++    DoWriteMemory(lldb::addr_t vm_addr, const void *buf, size_t size,
++                  lldb_private::Error &error) override;
++
++    lldb::addr_t
++    DoAllocateMemory(size_t size, uint32_t permissions,
++                     lldb_private::Error &error) override;
++
++    lldb_private::Error
++    DoDeallocateMemory(lldb::addr_t ptr) override;
++
++    virtual size_t
++    GetSoftwareBreakpointTrapOpcode(lldb_private::BreakpointSite* bp_site);
++
++    lldb_private::Error
++    EnableBreakpointSite(lldb_private::BreakpointSite *bp_site) override;
++
++    lldb_private::Error
++    DisableBreakpointSite(lldb_private::BreakpointSite *bp_site) override;
++
++    lldb_private::Error
++    EnableWatchpoint(lldb_private::Watchpoint *wp, bool notify = true) override;
++
++    lldb_private::Error
++    DisableWatchpoint(lldb_private::Watchpoint *wp, bool notify = true) override;
++
++    lldb_private::Error
++    GetWatchpointSupportInfo(uint32_t &num) override;
++
++    lldb_private::Error
++    GetWatchpointSupportInfo(uint32_t &num, bool &after) override;
++
++    virtual uint32_t
++    UpdateThreadListIfNeeded();
++
++    bool
++    UpdateThreadList(lldb_private::ThreadList &old_thread_list,
++                     lldb_private::ThreadList &new_thread_list) override;
++
++    virtual lldb::ByteOrder
++    GetByteOrder() const;
++
++    lldb::addr_t
++    GetImageInfoAddress() override;
++
++    size_t
++    PutSTDIN(const char *buf, size_t len, lldb_private::Error &error) override;
++
++    const lldb::DataBufferSP
++    GetAuxvData () override;
++
++    //--------------------------------------------------------------------------
++    // ProcessNetBSD internal API.
++
++    /// Registers the given message with this process.
++    virtual void
++    SendMessage(const ProcessMessage &message);
++
++    ProcessMonitor &
++    GetMonitor() { assert(m_monitor); return *m_monitor; }
++
++    lldb_private::FileSpec
++    GetFileSpec(const lldb_private::FileAction *file_action,
++                const lldb_private::FileSpec &default_file_spec,
++                const lldb_private::FileSpec &dbg_pts_file_spec);
++
++    /// Adds the thread to the list of threads for which we have received the initial stopping signal.
++    /// The \p stop_tid parameter indicates the thread which the stop happened for.
++    bool
++    AddThreadForInitialStopIfNeeded(lldb::tid_t stop_tid);
++
++    bool
++    WaitingForInitialStop(lldb::tid_t stop_tid);
++
++    virtual NetBSDThread *
++    CreateNewNetBSDThread(lldb_private::Process &process, lldb::tid_t tid);
++
++protected:
++    /// Target byte order.
++    lldb::ByteOrder m_byte_order;
++
++    /// Process monitor;
++    ProcessMonitor *m_monitor;
++
++    /// The module we are executing.
++    lldb_private::Module *m_module;
++
++    /// Message queue notifying this instance of inferior process state changes.
++    lldb_private::Mutex m_message_mutex;
++    std::queue<ProcessMessage> m_message_queue;
++
++    /// Drive any exit events to completion.
++    bool m_exit_now;
++
++    /// Returns true if the process has exited.
++    bool HasExited();
++
++    /// Returns true if the process is stopped.
++    bool IsStopped();
++
++    /// Returns true if at least one running is currently running
++    bool IsAThreadRunning();
++
++    typedef std::map<lldb::addr_t, lldb::addr_t> MMapMap;
++    MMapMap m_addr_to_mmap_size;
++
++    typedef std::set<lldb::tid_t> ThreadStopSet;
++    /// Every thread begins with a stop signal. This keeps track
++    /// of the threads for which we have received the stop signal.
++    ThreadStopSet m_seen_initial_stop;
++
++    friend class NetBSDThread;
++
++    typedef std::vector<lldb::tid_t> tid_collection;
++    tid_collection m_suspend_tids;
++    tid_collection m_run_tids;
++    tid_collection m_step_tids;
++
++    int m_resume_signo;
++
++};
++
++#endif  // liblldb_ProcessNetBSD_H_
diff --git a/lldb-git/patches/patch-source_Plugins_Process_NetBSD_RegisterContextPOSIX.h b/lldb-git/patches/patch-source_Plugins_Process_NetBSD_RegisterContextPOSIX.h
new file mode 100644
index 0000000..7d0c92b
--- /dev/null
+++ b/lldb-git/patches/patch-source_Plugins_Process_NetBSD_RegisterContextPOSIX.h
@@ -0,0 +1,84 @@
+$NetBSD$
+
+--- source/Plugins/Process/NetBSD/RegisterContextPOSIX.h.orig	2016-05-03 20:18:09.467970089 +0000
++++ source/Plugins/Process/NetBSD/RegisterContextPOSIX.h
+@@ -0,0 +1,79 @@
++//===-- RegisterContextPOSIX.h --------------------------------*- C++ -*-===//
++//
++//                     The LLVM Compiler Infrastructure
++//
++// This file is distributed under the University of Illinois Open Source
++// License. See LICENSE.TXT for details.
++//
++//===----------------------------------------------------------------------===//
++
++#ifndef liblldb_RegisterContextPOSIX_H_
++#define liblldb_RegisterContextPOSIX_H_
++
++// C Includes
++// C++ Includes
++// Other libraries and framework includes
++#include "lldb/Core/ArchSpec.h"
++#include "lldb/Target/RegisterContext.h"
++#include "RegisterInfoInterface.h"
++
++//------------------------------------------------------------------------------
++/// @class POSIXBreakpointProtocol
++///
++/// @brief Extends RegisterClass with a few virtual operations useful on POSIX.
++class POSIXBreakpointProtocol
++{
++public:
++    POSIXBreakpointProtocol()
++        { m_watchpoints_initialized = false; }
++    virtual ~POSIXBreakpointProtocol() {}
++
++    /// Updates the register state of the associated thread after hitting a
++    /// breakpoint (if that make sense for the architecture).  Default
++    /// implementation simply returns true for architectures which do not
++    /// require any update.
++    ///
++    /// @return
++    ///    True if the operation succeeded and false otherwise.
++    virtual bool UpdateAfterBreakpoint() = 0;
++
++    /// Determines the index in lldb's register file given a kernel byte offset.
++    virtual unsigned
++    GetRegisterIndexFromOffset(unsigned offset) = 0;
++
++    // Checks to see if a watchpoint specified by hw_index caused the inferior
++    // to stop.
++    virtual bool
++    IsWatchpointHit (uint32_t hw_index) = 0;
++
++    // Resets any watchpoints that have been hit.
++    virtual bool
++    ClearWatchpointHits () = 0;
++
++    // Returns the watchpoint address associated with a watchpoint hardware
++    // index.
++    virtual lldb::addr_t
++    GetWatchpointAddress (uint32_t hw_index) = 0;
++
++    virtual bool
++    IsWatchpointVacant (uint32_t hw_index) = 0;
++
++    virtual bool
++    SetHardwareWatchpointWithIndex (lldb::addr_t addr, size_t size,
++                                    bool read, bool write,
++                                    uint32_t hw_index) = 0;
++
++    // From lldb_private::RegisterContext
++    virtual uint32_t
++    NumSupportedHardwareWatchpoints () = 0;
++
++    // Force m_watchpoints_initialized to TRUE
++    void
++    ForceWatchpointsInitialized () {m_watchpoints_initialized = true;}
++
++protected:
++    bool m_watchpoints_initialized;
++};
++
++#endif // #ifndef liblldb_RegisterContextPOSIX_H_
++
diff --git a/lldb-git/patches/patch-source_Plugins_Process_NetBSD_RegisterContextPOSIXProcessMonitor__x86.cpp b/lldb-git/patches/patch-source_Plugins_Process_NetBSD_RegisterContextPOSIXProcessMonitor__x86.cpp
new file mode 100644
index 0000000..906e4a3
--- /dev/null
+++ b/lldb-git/patches/patch-source_Plugins_Process_NetBSD_RegisterContextPOSIXProcessMonitor__x86.cpp
@@ -0,0 +1,623 @@
+$NetBSD$
+
+--- source/Plugins/Process/NetBSD/RegisterContextPOSIXProcessMonitor_x86.cpp.orig	2016-05-03 20:18:09.474357842 +0000
++++ source/Plugins/Process/NetBSD/RegisterContextPOSIXProcessMonitor_x86.cpp
+@@ -0,0 +1,618 @@
++//===-- RegisterContextPOSIXProcessMonitor_x86.h ---------------*- C++ -*-===//
++//
++//                     The LLVM Compiler Infrastructure
++//
++// This file is distributed under the University of Illinois Open Source
++// License. See LICENSE.TXT for details.
++//
++//===---------------------------------------------------------------------===//
++
++#include "lldb/Core/DataBufferHeap.h"
++#include "lldb/Core/RegisterValue.h"
++#include "lldb/Target/Thread.h"
++
++#include "Plugins/Process/NetBSD/ProcessNetBSD.h"
++#include "RegisterContextPOSIXProcessMonitor_x86.h"
++#include "Plugins/Process/NetBSD/ProcessMonitor.h"
++
++using namespace lldb_private;
++using namespace lldb;
++
++// Support ptrace extensions even when compiled without required kernel support
++#ifndef NT_X86_XSTATE
++  #define NT_X86_XSTATE 0x202
++#endif
++
++#define REG_CONTEXT_SIZE (GetGPRSize() + sizeof(FPR))
++
++static uint32_t
++size_and_rw_bits(size_t size, bool read, bool write)
++{
++    uint32_t rw;
++
++    if (read)
++        rw = 0x3; // READ or READ/WRITE
++    else if (write)
++        rw = 0x1; // WRITE
++    else
++        assert(0 && "read and write cannot both be false");
++
++    switch (size)
++    {
++    case 1:
++        return rw;
++    case 2:
++        return (0x1 << 2) | rw;
++    case 4:
++        return (0x3 << 2) | rw;
++    case 8:
++        return (0x2 << 2) | rw;
++    default:
++        assert(0 && "invalid size, must be one of 1, 2, 4, or 8");
++        return 0; // Unreachable. Just to silence compiler.
++    }
++}
++
++RegisterContextPOSIXProcessMonitor_x86_64::RegisterContextPOSIXProcessMonitor_x86_64(Thread &thread,
++                                                                                     uint32_t concrete_frame_idx,
++                                                                                     lldb_private::RegisterInfoInterface *register_info)
++    : RegisterContextPOSIX_x86(thread, concrete_frame_idx, register_info)
++{
++    // Store byte offset of fctrl (i.e. first register of FPR) wrt 'UserArea'
++    const RegisterInfo *reg_info_fctrl = GetRegisterInfoByName("fctrl");
++    m_fctrl_offset_in_userarea = reg_info_fctrl->byte_offset;
++}
++
++ProcessMonitor &
++RegisterContextPOSIXProcessMonitor_x86_64::GetMonitor()
++{
++    ProcessSP base = CalculateProcess();
++    ProcessNetBSD *process = static_cast<ProcessNetBSD*>(base.get());
++    return process->GetMonitor();
++}
++
++bool
++RegisterContextPOSIXProcessMonitor_x86_64::ReadGPR()
++{
++     ProcessMonitor &monitor = GetMonitor();
++     return monitor.ReadGPR(m_thread.GetID(), &m_gpr_x86_64, GetGPRSize());
++}
++
++bool
++RegisterContextPOSIXProcessMonitor_x86_64::ReadFPR()
++{
++    ProcessMonitor &monitor = GetMonitor();
++    if (GetFPRType() == eFXSAVE)
++        return monitor.ReadFPR(m_thread.GetID(), &m_fpr.xstate.fxsave, sizeof(m_fpr.xstate.fxsave));
++
++    if (GetFPRType() == eXSAVE)
++        return monitor.ReadRegisterSet(m_thread.GetID(), &m_iovec, sizeof(m_fpr.xstate.xsave), NT_X86_XSTATE);
++    return false;
++}
++
++bool
++RegisterContextPOSIXProcessMonitor_x86_64::WriteGPR()
++{
++    ProcessMonitor &monitor = GetMonitor();
++    return monitor.WriteGPR(m_thread.GetID(), &m_gpr_x86_64, GetGPRSize());
++}
++
++bool
++RegisterContextPOSIXProcessMonitor_x86_64::WriteFPR()
++{
++    ProcessMonitor &monitor = GetMonitor();
++    if (GetFPRType() == eFXSAVE)
++        return monitor.WriteFPR(m_thread.GetID(), &m_fpr.xstate.fxsave, sizeof(m_fpr.xstate.fxsave));
++
++    if (GetFPRType() == eXSAVE)
++        return monitor.WriteRegisterSet(m_thread.GetID(), &m_iovec, sizeof(m_fpr.xstate.xsave), NT_X86_XSTATE);
++    return false;
++}
++
++bool
++RegisterContextPOSIXProcessMonitor_x86_64::ReadRegister(const unsigned reg,
++                                                        RegisterValue &value)
++{
++    ProcessMonitor &monitor = GetMonitor();
++
++    return monitor.ReadRegisterValue(m_thread.GetID(),
++                                     GetRegisterOffset(reg),
++                                     GetRegisterName(reg),
++                                     GetRegisterSize(reg),
++                                     value);
++}
++
++bool
++RegisterContextPOSIXProcessMonitor_x86_64::WriteRegister(const unsigned reg,
++                                                         const RegisterValue &value)
++{
++    unsigned reg_to_write = reg;
++    RegisterValue value_to_write = value;
++
++    // Check if this is a subregister of a full register.
++    const RegisterInfo *reg_info = GetRegisterInfoAtIndex(reg);
++    if (reg_info->invalidate_regs && (reg_info->invalidate_regs[0] != LLDB_INVALID_REGNUM))
++    {
++        RegisterValue full_value;
++        uint32_t full_reg = reg_info->invalidate_regs[0];
++        const RegisterInfo *full_reg_info = GetRegisterInfoAtIndex(full_reg);
++
++        // Read the full register.
++        if (ReadRegister(full_reg_info, full_value))
++        {
++            Error error;
++            ByteOrder byte_order = GetByteOrder();
++            uint8_t dst[RegisterValue::kMaxRegisterByteSize];
++
++            // Get the bytes for the full register.
++            const uint32_t dest_size = full_value.GetAsMemoryData (full_reg_info, 
++                                                                   dst, 
++                                                                   sizeof(dst), 
++                                                                   byte_order, 
++                                                                   error);
++            if (error.Success() && dest_size)
++            {
++                uint8_t src[RegisterValue::kMaxRegisterByteSize];
++
++                // Get the bytes for the source data.
++                const uint32_t src_size = value.GetAsMemoryData (reg_info, src, sizeof(src), byte_order, error);
++                if (error.Success() && src_size && (src_size < dest_size))
++                {
++                    // Copy the src bytes to the destination.
++                    memcpy (dst + (reg_info->byte_offset & 0x1), src, src_size);
++                    // Set this full register as the value to write.
++                    value_to_write.SetBytes(dst, full_value.GetByteSize(), byte_order);
++                    value_to_write.SetType(full_reg_info);
++                    reg_to_write = full_reg;
++                }
++            }
++        }
++    }
++
++    ProcessMonitor &monitor = GetMonitor();
++
++    return monitor.WriteRegisterValue(m_thread.GetID(),
++                                      GetRegisterOffset(reg_to_write),
++                                      GetRegisterName(reg_to_write),
++                                      value_to_write);
++}
++
++bool
++RegisterContextPOSIXProcessMonitor_x86_64::ReadRegister(const RegisterInfo *reg_info, RegisterValue &value)
++{
++    if (!reg_info)
++        return false;
++
++    const uint32_t reg = reg_info->kinds[eRegisterKindLLDB];
++
++    if (IsFPR(reg, GetFPRType()))
++    {
++        if (!ReadFPR())
++            return false;
++    }
++    else
++    {
++        uint32_t full_reg = reg;
++        bool is_subreg = reg_info->invalidate_regs && (reg_info->invalidate_regs[0] != LLDB_INVALID_REGNUM);
++
++        if (is_subreg)
++        {
++            // Read the full aligned 64-bit register.
++            full_reg = reg_info->invalidate_regs[0];
++        }
++
++        bool success = ReadRegister(full_reg, value);
++
++        if (success)
++        {
++            // If our read was not aligned (for ah,bh,ch,dh), shift our returned value one byte to the right.
++            if (is_subreg && (reg_info->byte_offset & 0x1))
++                value.SetUInt64(value.GetAsUInt64() >> 8);
++
++            // If our return byte size was greater than the return value reg size, then
++            // use the type specified by reg_info rather than the uint64_t default
++            if (value.GetByteSize() > reg_info->byte_size)
++                value.SetType(reg_info);
++        }
++        return success; 
++    }
++
++    if (reg_info->encoding == eEncodingVector)
++    {
++        ByteOrder byte_order = GetByteOrder();
++
++        if (byte_order != ByteOrder::eByteOrderInvalid)
++        {
++            if (reg >= m_reg_info.first_st && reg <= m_reg_info.last_st)
++               value.SetBytes(m_fpr.xstate.fxsave.stmm[reg - m_reg_info.first_st].bytes, reg_info->byte_size, byte_order);
++            if (reg >= m_reg_info.first_mm && reg <= m_reg_info.last_mm)
++               value.SetBytes(m_fpr.xstate.fxsave.stmm[reg - m_reg_info.first_mm].bytes, reg_info->byte_size, byte_order);
++            if (reg >= m_reg_info.first_xmm && reg <= m_reg_info.last_xmm)
++                value.SetBytes(m_fpr.xstate.fxsave.xmm[reg - m_reg_info.first_xmm].bytes, reg_info->byte_size, byte_order);
++            if (reg >= m_reg_info.first_ymm && reg <= m_reg_info.last_ymm)
++            {
++                // Concatenate ymm using the register halves in xmm.bytes and ymmh.bytes
++                if (GetFPRType() == eXSAVE && CopyXSTATEtoYMM(reg, byte_order))
++                    value.SetBytes(m_ymm_set.ymm[reg - m_reg_info.first_ymm].bytes, reg_info->byte_size, byte_order);
++                else
++                    return false;
++            }
++            return value.GetType() == RegisterValue::eTypeBytes;
++        }
++        return false;
++    }
++
++    // Get pointer to m_fpr.xstate.fxsave variable and set the data from it.
++    // Byte offsets of all registers are calculated wrt 'UserArea' structure.
++    // However, ReadFPR() reads fpu registers {using ptrace(PT_GETFPREGS,..)}
++    // and stores them in 'm_fpr' (of type FPR structure). To extract values of fpu
++    // registers, m_fpr should be read at byte offsets calculated wrt to FPR structure.
++
++    // Since, FPR structure is also one of the member of UserArea structure.
++    // byte_offset(fpu wrt FPR) = byte_offset(fpu wrt UserArea) - byte_offset(fctrl wrt UserArea)
++    assert ( (reg_info->byte_offset - m_fctrl_offset_in_userarea) < sizeof(m_fpr));
++    uint8_t *src = (uint8_t *)&m_fpr + reg_info->byte_offset - m_fctrl_offset_in_userarea;
++    switch (reg_info->byte_size)
++    {
++        case 1:
++            value.SetUInt8(*(uint8_t *)src);
++            return true;
++        case 2:
++            value.SetUInt16(*(uint16_t *)src);
++            return true;
++        case 4:
++            value.SetUInt32(*(uint32_t *)src);
++            return true;
++        case 8:
++            value.SetUInt64(*(uint64_t *)src);
++            return true;
++        default:
++            assert(false && "Unhandled data size.");
++            return false;
++    }
++}
++
++bool
++RegisterContextPOSIXProcessMonitor_x86_64::WriteRegister(const RegisterInfo *reg_info, const RegisterValue &value)
++{
++    const uint32_t reg = reg_info->kinds[eRegisterKindLLDB];
++
++    if (IsGPR(reg))
++        return WriteRegister(reg, value);
++
++    if (IsFPR(reg, GetFPRType()))
++    {
++        if (reg_info->encoding == eEncodingVector)
++        {
++            if (reg >= m_reg_info.first_st && reg <= m_reg_info.last_st)
++               ::memcpy (m_fpr.xstate.fxsave.stmm[reg - m_reg_info.first_st].bytes, value.GetBytes(), value.GetByteSize());
++
++            if (reg >= m_reg_info.first_mm && reg <= m_reg_info.last_mm)
++               ::memcpy (m_fpr.xstate.fxsave.stmm[reg - m_reg_info.first_mm].bytes, value.GetBytes(), value.GetByteSize());
++ 
++            if (reg >= m_reg_info.first_xmm && reg <= m_reg_info.last_xmm)
++               ::memcpy (m_fpr.xstate.fxsave.xmm[reg - m_reg_info.first_xmm].bytes, value.GetBytes(), value.GetByteSize());
++            
++            if (reg >= m_reg_info.first_ymm && reg <= m_reg_info.last_ymm)
++            {
++               if (GetFPRType() != eXSAVE)
++                   return false; // the target processor does not support AVX
++
++               // Store ymm register content, and split into the register halves in xmm.bytes and ymmh.bytes
++               ::memcpy (m_ymm_set.ymm[reg - m_reg_info.first_ymm].bytes, value.GetBytes(), value.GetByteSize());
++               if (false == CopyYMMtoXSTATE(reg, GetByteOrder()))
++                   return false;
++            }
++        }
++        else
++        {
++            // Get pointer to m_fpr.xstate.fxsave variable and set the data to it.
++            // Byte offsets of all registers are calculated wrt 'UserArea' structure.
++            // However, WriteFPR() takes m_fpr (of type FPR structure) and writes only fpu
++            // registers using ptrace(PT_SETFPREGS,..) API. Hence fpu registers should
++            // be written in m_fpr at byte offsets calculated wrt FPR structure.
++
++            // Since, FPR structure is also one of the member of UserArea structure.
++            // byte_offset(fpu wrt FPR) = byte_offset(fpu wrt UserArea) - byte_offset(fctrl wrt UserArea)
++            assert ( (reg_info->byte_offset - m_fctrl_offset_in_userarea) < sizeof(m_fpr));
++            uint8_t *dst = (uint8_t *)&m_fpr + reg_info->byte_offset - m_fctrl_offset_in_userarea;
++            switch (reg_info->byte_size)
++            {
++                case 1:
++                    *(uint8_t *)dst = value.GetAsUInt8();
++                    break;
++                case 2:
++                    *(uint16_t *)dst = value.GetAsUInt16();
++                    break;
++                case 4:
++                    *(uint32_t *)dst = value.GetAsUInt32();
++                    break;
++                case 8:
++                    *(uint64_t *)dst = value.GetAsUInt64();
++                    break;
++                default:
++                    assert(false && "Unhandled data size.");
++                    return false;
++            }
++        }
++
++        if (WriteFPR())
++        {
++            if (IsAVX(reg))
++                return CopyYMMtoXSTATE(reg, GetByteOrder());
++            return true;
++        }
++    }
++    return false;
++}
++
++bool
++RegisterContextPOSIXProcessMonitor_x86_64::ReadAllRegisterValues(DataBufferSP &data_sp)
++{
++    bool success = false;
++    data_sp.reset (new DataBufferHeap (REG_CONTEXT_SIZE, 0));
++    if (data_sp && ReadGPR () && ReadFPR ())
++    {
++        uint8_t *dst = data_sp->GetBytes();
++        success = dst != 0;
++
++        if (success)
++        {
++          ::memcpy (dst, &m_gpr_x86_64, GetGPRSize());
++          dst += GetGPRSize();
++          if (GetFPRType() == eFXSAVE)
++              ::memcpy (dst, &m_fpr.xstate.fxsave, sizeof(m_fpr.xstate.fxsave));
++        }
++
++        if (GetFPRType() == eXSAVE)
++        {
++            ByteOrder byte_order = GetByteOrder();
++
++            // Assemble the YMM register content from the register halves.
++            for (uint32_t reg  = m_reg_info.first_ymm; success && reg <= m_reg_info.last_ymm; ++reg)
++                success = CopyXSTATEtoYMM(reg, byte_order);
++
++            if (success)
++            {
++                // Copy the extended register state including the assembled ymm registers.
++                ::memcpy (dst, &m_fpr, sizeof(m_fpr));
++            }
++        }
++    }
++    return success;
++}
++
++bool
++RegisterContextPOSIXProcessMonitor_x86_64::WriteAllRegisterValues(const DataBufferSP &data_sp)
++{
++    bool success = false;
++    if (data_sp && data_sp->GetByteSize() == REG_CONTEXT_SIZE)
++    {
++        uint8_t *src = data_sp->GetBytes();
++        if (src)
++        {
++            ::memcpy (&m_gpr_x86_64, src, GetGPRSize());
++
++            if (WriteGPR())
++            {
++                src += GetGPRSize();
++                if (GetFPRType() == eFXSAVE)
++                    ::memcpy (&m_fpr.xstate.fxsave, src, sizeof(m_fpr.xstate.fxsave));
++                if (GetFPRType() == eXSAVE)
++                    ::memcpy (&m_fpr.xstate.xsave, src, sizeof(m_fpr.xstate.xsave));
++
++                success = WriteFPR();
++                if (success)
++                {
++                    if (GetFPRType() == eXSAVE)
++                    {
++                        ByteOrder byte_order = GetByteOrder();
++
++                        // Parse the YMM register content from the register halves.
++                        for (uint32_t reg = m_reg_info.first_ymm; success && reg <= m_reg_info.last_ymm; ++reg)
++                            success = CopyYMMtoXSTATE(reg, byte_order);
++                    }
++                }
++            }
++        }
++    }
++    return success;
++}
++
++uint32_t
++RegisterContextPOSIXProcessMonitor_x86_64::SetHardwareWatchpoint(addr_t addr, size_t size,
++                                              bool read, bool write)
++{
++    const uint32_t num_hw_watchpoints = NumSupportedHardwareWatchpoints();
++    uint32_t hw_index;
++
++    for (hw_index = 0; hw_index < num_hw_watchpoints; ++hw_index)
++    {
++        if (IsWatchpointVacant(hw_index))
++            return SetHardwareWatchpointWithIndex(addr, size,
++                                                  read, write,
++                                                  hw_index);
++    }
++
++    return LLDB_INVALID_INDEX32;
++}
++
++bool
++RegisterContextPOSIXProcessMonitor_x86_64::ClearHardwareWatchpoint(uint32_t hw_index)
++{
++    if (hw_index < NumSupportedHardwareWatchpoints())
++    {
++        RegisterValue current_dr7_bits;
++
++        if (ReadRegister(m_reg_info.first_dr + 7, current_dr7_bits))
++        {
++            uint64_t new_dr7_bits = current_dr7_bits.GetAsUInt64() & ~(3 << (2*hw_index));
++
++            if (WriteRegister(m_reg_info.first_dr + 7, RegisterValue(new_dr7_bits)))
++                return true;
++        }
++    }
++
++    return false;
++}
++
++bool
++RegisterContextPOSIXProcessMonitor_x86_64::HardwareSingleStep(bool enable)
++{
++    enum { TRACE_BIT = 0x100 };
++    uint64_t rflags;
++
++    if ((rflags = ReadRegisterAsUnsigned(m_reg_info.gpr_flags, -1UL)) == -1UL)
++        return false;
++    
++    if (enable)
++    {
++        if (rflags & TRACE_BIT)
++            return true;
++
++        rflags |= TRACE_BIT;
++    }
++    else
++    {
++        if (!(rflags & TRACE_BIT))
++            return false;
++
++        rflags &= ~TRACE_BIT;
++    }
++
++    return WriteRegisterFromUnsigned(m_reg_info.gpr_flags, rflags);
++}
++
++bool
++RegisterContextPOSIXProcessMonitor_x86_64::UpdateAfterBreakpoint()
++{
++    // PC points one byte past the int3 responsible for the breakpoint.
++    lldb::addr_t pc;
++
++    if ((pc = GetPC()) == LLDB_INVALID_ADDRESS)
++        return false;
++
++    SetPC(pc - 1);
++    return true;
++}
++
++unsigned
++RegisterContextPOSIXProcessMonitor_x86_64::GetRegisterIndexFromOffset(unsigned offset)
++{
++    unsigned reg;
++    for (reg = 0; reg < m_reg_info.num_registers; reg++)
++    {
++        if (GetRegisterInfo()[reg].byte_offset == offset)
++            break;
++    }
++    assert(reg < m_reg_info.num_registers && "Invalid register offset.");
++    return reg;
++}
++
++bool
++RegisterContextPOSIXProcessMonitor_x86_64::IsWatchpointHit(uint32_t hw_index)
++{
++    bool is_hit = false;
++
++    if (m_watchpoints_initialized == false)
++    {    
++        // Reset the debug status and debug control registers
++        RegisterValue zero_bits = RegisterValue(uint64_t(0));
++        if (!WriteRegister(m_reg_info.first_dr + 6, zero_bits) || !WriteRegister(m_reg_info.first_dr + 7, zero_bits))
++            assert(false && "Could not initialize watchpoint registers");
++        m_watchpoints_initialized = true;
++    }    
++
++    if (hw_index < NumSupportedHardwareWatchpoints())
++    {    
++        RegisterValue value;
++
++        if (ReadRegister(m_reg_info.first_dr + 6, value))
++        {    
++            uint64_t val = value.GetAsUInt64();
++            is_hit = val & (1 << hw_index);
++        }    
++    }    
++
++    return is_hit;
++}
++
++bool
++RegisterContextPOSIXProcessMonitor_x86_64::ClearWatchpointHits()
++{
++    return WriteRegister(m_reg_info.first_dr + 6, RegisterValue((uint64_t)0));
++}
++
++addr_t
++RegisterContextPOSIXProcessMonitor_x86_64::GetWatchpointAddress(uint32_t hw_index)
++{
++    addr_t wp_monitor_addr = LLDB_INVALID_ADDRESS;
++
++    if (hw_index < NumSupportedHardwareWatchpoints())
++    {
++        if (!IsWatchpointVacant(hw_index))
++        {
++            RegisterValue value;
++
++            if (ReadRegister(m_reg_info.first_dr + hw_index, value))
++                wp_monitor_addr = value.GetAsUInt64();
++        }
++    }
++
++    return wp_monitor_addr;
++}
++
++bool
++RegisterContextPOSIXProcessMonitor_x86_64::IsWatchpointVacant(uint32_t hw_index)
++{
++    bool is_vacant = false;
++    RegisterValue value;
++
++    assert(hw_index < NumSupportedHardwareWatchpoints());
++
++    if (m_watchpoints_initialized == false)
++    {
++        // Reset the debug status and debug control registers
++        RegisterValue zero_bits = RegisterValue(uint64_t(0));
++        if (!WriteRegister(m_reg_info.first_dr + 6, zero_bits) || !WriteRegister(m_reg_info.first_dr + 7, zero_bits))
++            assert(false && "Could not initialize watchpoint registers");
++        m_watchpoints_initialized = true;
++    }
++
++    if (ReadRegister(m_reg_info.first_dr + 7, value))
++    {
++        uint64_t val = value.GetAsUInt64();
++        is_vacant = (val & (3 << 2*hw_index)) == 0;
++    }
++
++    return is_vacant;
++}
++
++bool
++RegisterContextPOSIXProcessMonitor_x86_64::SetHardwareWatchpointWithIndex(addr_t addr, size_t size,
++                                                       bool read, bool write,
++                                                       uint32_t hw_index)
++{
++    const uint32_t num_hw_watchpoints = NumSupportedHardwareWatchpoints();
++
++    if (num_hw_watchpoints == 0 || hw_index >= num_hw_watchpoints)
++        return false;
++
++    if (!(size == 1 || size == 2 || size == 4 || size == 8))
++        return false;
++
++    if (read == false && write == false)
++        return false;
++
++    if (!IsWatchpointVacant(hw_index))
++        return false;
++
++    return false;
++}
++
++uint32_t
++RegisterContextPOSIXProcessMonitor_x86_64::NumSupportedHardwareWatchpoints()
++{
++    // Available debug address registers: NONE
++    return 0;
++}
diff --git a/lldb-git/patches/patch-source_Plugins_Process_NetBSD_RegisterContextPOSIXProcessMonitor__x86.h b/lldb-git/patches/patch-source_Plugins_Process_NetBSD_RegisterContextPOSIXProcessMonitor__x86.h
new file mode 100644
index 0000000..7e8485c
--- /dev/null
+++ b/lldb-git/patches/patch-source_Plugins_Process_NetBSD_RegisterContextPOSIXProcessMonitor__x86.h
@@ -0,0 +1,102 @@
+$NetBSD$
+
+--- source/Plugins/Process/NetBSD/RegisterContextPOSIXProcessMonitor_x86.h.orig	2016-05-03 20:18:09.480714306 +0000
++++ source/Plugins/Process/NetBSD/RegisterContextPOSIXProcessMonitor_x86.h
+@@ -0,0 +1,97 @@
++//===-- RegisterContextPOSIXProcessMonitor_x86.h ----------------*- C++ -*-===//
++//
++//                     The LLVM Compiler Infrastructure
++//
++// This file is distributed under the University of Illinois Open Source
++// License. See LICENSE.TXT for details.
++//
++//===----------------------------------------------------------------------===//
++
++#ifndef liblldb_RegisterContextPOSIXProcessMonitor_x86_H_
++#define liblldb_RegisterContextPOSIXProcessMonitor_x86_H_
++
++#include "RegisterContextPOSIX.h"
++#include "Plugins/Process/Utility/RegisterContextPOSIX_x86.h"
++
++class RegisterContextPOSIXProcessMonitor_x86_64:
++    public RegisterContextPOSIX_x86,
++    public POSIXBreakpointProtocol
++{
++public:
++    RegisterContextPOSIXProcessMonitor_x86_64(lldb_private::Thread &thread,
++                                              uint32_t concrete_frame_idx,
++                                              lldb_private::RegisterInfoInterface *register_info);
++
++protected:
++    bool
++    ReadGPR();
++
++    bool
++    ReadFPR();
++
++    bool
++    WriteGPR();
++
++    bool
++    WriteFPR();
++
++    // lldb_private::RegisterContext
++    bool
++    ReadRegister(const unsigned reg, lldb_private::RegisterValue &value);
++
++    bool
++    WriteRegister(const unsigned reg, const lldb_private::RegisterValue &value);
++
++    bool
++    ReadRegister(const lldb_private::RegisterInfo *reg_info, lldb_private::RegisterValue &value);
++
++    bool
++    WriteRegister(const lldb_private::RegisterInfo *reg_info, const lldb_private::RegisterValue &value);
++
++    bool
++    ReadAllRegisterValues(lldb::DataBufferSP &data_sp);
++
++    bool
++    WriteAllRegisterValues(const lldb::DataBufferSP &data_sp);
++
++    uint32_t
++    SetHardwareWatchpoint(lldb::addr_t addr, size_t size, bool read, bool write);
++
++    bool
++    ClearHardwareWatchpoint(uint32_t hw_index);
++
++    bool
++    HardwareSingleStep(bool enable);
++
++    // POSIXBreakpointProtocol
++    bool
++    UpdateAfterBreakpoint();
++
++    unsigned
++    GetRegisterIndexFromOffset(unsigned offset);
++
++    bool
++    IsWatchpointHit(uint32_t hw_index);
++
++    bool
++    ClearWatchpointHits();
++
++    lldb::addr_t
++    GetWatchpointAddress(uint32_t hw_index);
++
++    bool
++    IsWatchpointVacant(uint32_t hw_index);
++
++    bool
++    SetHardwareWatchpointWithIndex(lldb::addr_t addr, size_t size, bool read, bool write, uint32_t hw_index);
++
++    uint32_t
++    NumSupportedHardwareWatchpoints();
++
++private:
++    ProcessMonitor &
++    GetMonitor();
++    uint32_t m_fctrl_offset_in_userarea;  // Offset of 'fctrl' in 'UserArea' Structure
++};
++
++#endif


Home | Main Index | Thread Index | Old Index