Added a new plug-in type: lldb_private::OperatingSystem. The operating system 
plug-ins are add on plug-ins for the lldb_private::Process class that can add
thread contexts that are read from memory. It is common in kernels to have
a lot of threads that are not currently executing on any cores (JTAG debugging
also follows this sort of thing) and are context switched out whose state is
stored in memory data structures. Clients can now subclass the OperatingSystem
plug-ins and then make sure their Create functions correcltly only enable 
themselves when the right binary/target triple are being debugged. The 
operating system plug-ins get a chance to attach themselves to processes just
after launching or attaching and are given a lldb_private::Process object 
pointer which can be inspected to see if the main executable, target triple,
or any shared  libraries match a case where the OS plug-in should be used.
Currently the OS plug-ins can create new threads, define the register contexts
for these threads (which can all be different if desired), and populate and
manage the thread info (stop reason, registers in the register context) as
the debug session goes on.



git-svn-id: https://llvm.org/svn/llvm-project/llvdb/trunk@138228 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.cpp b/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.cpp
index 401fd9a..a841220 100644
--- a/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.cpp
+++ b/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.cpp
@@ -185,7 +185,7 @@
                     kernel_arch.SetArchitecture(eArchTypeMachO, cpu, sub);
                     m_target.SetArchitecture(kernel_arch);
                     SetID (1);
-                    UpdateThreadListIfNeeded ();
+                    GetThreadList ();
                     SetPrivateState (eStateStopped);
                     StreamSP async_strm_sp(m_target.GetDebugger().GetAsyncOutputStream());
                     if (async_strm_sp)
@@ -289,34 +289,28 @@
 }
 
 uint32_t
-ProcessKDP::UpdateThreadListIfNeeded ()
+ProcessKDP::UpdateThreadList (ThreadList &old_thread_list, ThreadList &new_thread_list)
 {
     // locker will keep a mutex locked until it goes out of scope
     LogSP log (ProcessKDPLog::GetLogIfAllCategoriesSet (KDP_LOG_THREAD));
     if (log && log->GetMask().Test(KDP_LOG_VERBOSE))
         log->Printf ("ProcessKDP::%s (pid = %i)", __FUNCTION__, GetID());
     
-    Mutex::Locker locker (m_thread_list.GetMutex ());
-    const uint32_t stop_id = GetStopID();
-    if (m_thread_list.GetSize(false) == 0)
+    // We currently are making only one thread per core and we
+    // actually don't know about actual threads. Eventually we
+    // want to get the thread list from memory and note which
+    // threads are on CPU as those are the only ones that we 
+    // will be able to resume.
+    const uint32_t cpu_mask = m_comm.GetCPUMask();
+    for (uint32_t cpu_mask_bit = 1; cpu_mask_bit & cpu_mask; cpu_mask_bit <<= 1)
     {
-        // We currently are making only one thread per core and we
-        // actually don't know about actual threads. Eventually we
-        // want to get the thread list from memory and note which
-        // threads are on CPU as those are the only ones that we 
-        // will be able to resume.
-        ThreadList curr_thread_list (this);
-        curr_thread_list.SetStopID(stop_id);
-        const uint32_t cpu_mask = m_comm.GetCPUMask();
-        for (uint32_t cpu_mask_bit = 1; cpu_mask_bit & cpu_mask; cpu_mask_bit <<= 1)
-        {
-            // The thread ID is currently the CPU mask bit
-            ThreadSP thread_sp (new ThreadKDP (*this, cpu_mask_bit));
-                curr_thread_list.AddThread(thread_sp);
-        }
-        m_thread_list = curr_thread_list;
+        lldb::tid_t tid = cpu_mask_bit;
+        ThreadSP thread_sp (old_thread_list.FindThreadByID (tid, false));
+        if (!thread_sp)
+            thread_sp.reset(new ThreadKDP (*this, tid));
+        new_thread_list.AddThread(thread_sp);
     }
-    return GetThreadList().GetSize(false);
+    return new_thread_list.GetSize(false);
 }
 
 
diff --git a/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.h b/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.h
index 7f254d0..0590752 100644
--- a/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.h
+++ b/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.h
@@ -233,7 +233,8 @@
     Clear ( );
     
     uint32_t
-    UpdateThreadListIfNeeded ();
+    UpdateThreadList (lldb_private::ThreadList &old_thread_list, 
+                      lldb_private::ThreadList &new_thread_list);
     
     enum
     {
diff --git a/source/Plugins/Process/MacOSX-Kernel/ThreadKDP.cpp b/source/Plugins/Process/MacOSX-Kernel/ThreadKDP.cpp
index dac5517..d0c4afd 100644
--- a/source/Plugins/Process/MacOSX-Kernel/ThreadKDP.cpp
+++ b/source/Plugins/Process/MacOSX-Kernel/ThreadKDP.cpp
@@ -28,11 +28,6 @@
 #include "RegisterContextKDP_arm.h"
 #include "RegisterContextKDP_i386.h"
 #include "RegisterContextKDP_x86_64.h"
-#include "Plugins/Process/Utility/UnwindLLDB.h"
-
-#if defined(__APPLE__)
-#include "UnwindMacOSXFrameBackchain.h"
-#endif
 
 using namespace lldb;
 using namespace lldb_private;
@@ -56,14 +51,6 @@
     DestroyThread();
 }
 
-
-const char *
-ThreadKDP::GetInfo ()
-{
-    return NULL;
-}
-
-
 const char *
 ThreadKDP::GetName ()
 {
@@ -124,32 +111,6 @@
     GetRegisterContext()->InvalidateIfNeeded (force);
 }
 
-Unwind *
-ThreadKDP::GetUnwinder ()
-{
-    if (m_unwinder_ap.get() == NULL)
-    {
-        const ArchSpec target_arch (GetProcess().GetTarget().GetArchitecture ());
-        const llvm::Triple::ArchType machine = target_arch.GetMachine();
-        switch (machine)
-        {
-            case llvm::Triple::x86_64:
-            case llvm::Triple::x86:
-            case llvm::Triple::arm:
-            case llvm::Triple::thumb:
-                m_unwinder_ap.reset (new UnwindLLDB (*this));
-                break;
-
-            default:
-#if defined(__APPLE__)
-                m_unwinder_ap.reset (new UnwindMacOSXFrameBackchain (*this));
-#endif
-                break;
-        }
-    }
-    return m_unwinder_ap.get();
-}
-
 void
 ThreadKDP::ClearStackFrames ()
 {
diff --git a/source/Plugins/Process/MacOSX-Kernel/ThreadKDP.h b/source/Plugins/Process/MacOSX-Kernel/ThreadKDP.h
index 95c2f05..a37fa91 100644
--- a/source/Plugins/Process/MacOSX-Kernel/ThreadKDP.h
+++ b/source/Plugins/Process/MacOSX-Kernel/ThreadKDP.h
@@ -33,9 +33,6 @@
     RefreshStateAfterStop();
 
     virtual const char *
-    GetInfo ();
-
-    virtual const char *
     GetName ();
 
     virtual const char *
@@ -103,9 +100,6 @@
     // Member variables.
     //------------------------------------------------------------------
 
-    virtual lldb_private::Unwind *
-    GetUnwinder ();
-
     virtual lldb::StopInfoSP
     GetPrivateStopReason ();
 
diff --git a/source/Plugins/Process/Utility/DynamicRegisterInfo.cpp b/source/Plugins/Process/Utility/DynamicRegisterInfo.cpp
new file mode 100644
index 0000000..293ebac
--- /dev/null
+++ b/source/Plugins/Process/Utility/DynamicRegisterInfo.cpp
@@ -0,0 +1,142 @@
+//===-- DynamicRegisterInfo.cpp ----------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "DynamicRegisterInfo.h"
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+
+using namespace lldb;
+using namespace lldb_private;
+
+DynamicRegisterInfo::DynamicRegisterInfo () :
+    m_regs (),
+    m_sets (),
+    m_set_reg_nums (),
+    m_reg_names (),
+    m_reg_alt_names (),
+    m_set_names (),
+    m_reg_data_byte_size (0)
+{
+}
+
+DynamicRegisterInfo::~DynamicRegisterInfo ()
+{
+}
+
+void
+DynamicRegisterInfo::AddRegister (RegisterInfo &reg_info, 
+                                  ConstString &reg_name, 
+                                  ConstString &reg_alt_name, 
+                                  ConstString &set_name)
+{
+    const uint32_t reg_num = m_regs.size();
+    m_reg_names.push_back (reg_name);
+    m_reg_alt_names.push_back (reg_alt_name);
+    reg_info.name = reg_name.AsCString();
+    assert (reg_info.name);
+    reg_info.alt_name = reg_alt_name.AsCString(NULL);
+    m_regs.push_back (reg_info);
+    uint32_t set = GetRegisterSetIndexByName (set_name, true);
+    assert (set < m_sets.size());
+    assert (set < m_set_reg_nums.size());
+    assert (set < m_set_names.size());
+    m_set_reg_nums[set].push_back(reg_num);
+    size_t end_reg_offset = reg_info.byte_offset + reg_info.byte_size;
+    if (m_reg_data_byte_size < end_reg_offset)
+        m_reg_data_byte_size = end_reg_offset;
+}
+
+void
+DynamicRegisterInfo::Finalize ()
+{
+    for (uint32_t set = 0; set < m_sets.size(); ++set)
+    {
+        assert (m_sets.size() == m_set_reg_nums.size());
+        m_sets[set].num_registers = m_set_reg_nums[set].size();
+        m_sets[set].registers = &m_set_reg_nums[set][0];
+    }
+}
+
+size_t
+DynamicRegisterInfo::GetNumRegisters() const
+{
+    return m_regs.size();
+}
+
+size_t
+DynamicRegisterInfo::GetNumRegisterSets() const
+{
+    return m_sets.size();
+}
+
+size_t
+DynamicRegisterInfo::GetRegisterDataByteSize() const
+{
+    return m_reg_data_byte_size;
+}
+
+const RegisterInfo *
+DynamicRegisterInfo::GetRegisterInfoAtIndex (uint32_t i) const
+{
+    if (i < m_regs.size())
+        return &m_regs[i];
+    return NULL;
+}
+
+const RegisterSet *
+DynamicRegisterInfo::GetRegisterSet (uint32_t i) const
+{
+    if (i < m_sets.size())
+        return &m_sets[i];
+    return NULL;
+}
+
+uint32_t
+DynamicRegisterInfo::GetRegisterSetIndexByName (ConstString &set_name, bool can_create)
+{
+    name_collection::iterator pos, end = m_set_names.end();
+    for (pos = m_set_names.begin(); pos != end; ++pos)
+    {
+        if (*pos == set_name)
+            return std::distance (m_set_names.begin(), pos);
+    }
+    
+    m_set_names.push_back(set_name);
+    m_set_reg_nums.resize(m_set_reg_nums.size()+1);
+    RegisterSet new_set = { set_name.AsCString(), NULL, 0, NULL };
+    m_sets.push_back (new_set);
+    return m_sets.size() - 1;
+}
+
+uint32_t
+DynamicRegisterInfo::ConvertRegisterKindToRegisterNumber (uint32_t kind, uint32_t num) const
+{
+    reg_collection::const_iterator pos, end = m_regs.end();
+    for (pos = m_regs.begin(); pos != end; ++pos)
+    {
+        if (pos->kinds[kind] == num)
+            return std::distance (m_regs.begin(), pos);
+    }
+    
+    return LLDB_INVALID_REGNUM;
+}
+
+void
+DynamicRegisterInfo::Clear()
+{
+    m_regs.clear();
+    m_sets.clear();
+    m_set_reg_nums.clear();
+    m_reg_names.clear();
+    m_reg_alt_names.clear();
+    m_set_names.clear();
+}
diff --git a/source/Plugins/Process/Utility/DynamicRegisterInfo.h b/source/Plugins/Process/Utility/DynamicRegisterInfo.h
new file mode 100644
index 0000000..46841a0
--- /dev/null
+++ b/source/Plugins/Process/Utility/DynamicRegisterInfo.h
@@ -0,0 +1,82 @@
+//===-- DynamicRegisterInfo.h -----------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef lldb_DynamicRegisterInfo_h_
+#define lldb_DynamicRegisterInfo_h_
+
+// C Includes
+// C++ Includes
+#include <vector>
+
+// Other libraries and framework includes
+// Project includes
+#include "lldb/lldb-private.h"
+#include "lldb/Core/ConstString.h"
+
+class DynamicRegisterInfo
+{
+public:
+    DynamicRegisterInfo ();
+
+    virtual 
+    ~DynamicRegisterInfo ();
+
+    void
+    AddRegister (lldb_private::RegisterInfo &reg_info, 
+                 lldb_private::ConstString &reg_name, 
+                 lldb_private::ConstString &reg_alt_name, 
+                 lldb_private::ConstString &set_name);
+
+    void
+    Finalize ();
+
+    size_t
+    GetNumRegisters() const;
+
+    size_t
+    GetNumRegisterSets() const;
+
+    size_t
+    GetRegisterDataByteSize() const;
+
+    const lldb_private::RegisterInfo *
+    GetRegisterInfoAtIndex (uint32_t i) const;
+
+    const lldb_private::RegisterSet *
+    GetRegisterSet (uint32_t i) const;
+
+    uint32_t
+    GetRegisterSetIndexByName (lldb_private::ConstString &set_name, bool can_create);
+
+    uint32_t
+    ConvertRegisterKindToRegisterNumber (uint32_t kind, uint32_t num) const;
+
+    void
+    Clear();
+
+protected:
+    //------------------------------------------------------------------
+    // Classes that inherit from DynamicRegisterInfo can see and modify these
+    //------------------------------------------------------------------
+    typedef std::vector <lldb_private::RegisterInfo> reg_collection;
+    typedef std::vector <lldb_private::RegisterSet> set_collection;
+    typedef std::vector <uint32_t> reg_num_collection;
+    typedef std::vector <reg_num_collection> set_reg_num_collection;
+    typedef std::vector <lldb_private::ConstString> name_collection;
+
+    reg_collection m_regs;
+    set_collection m_sets;
+    set_reg_num_collection m_set_reg_nums;
+    name_collection m_reg_names;
+    name_collection m_reg_alt_names;
+    name_collection m_set_names;
+    size_t m_reg_data_byte_size;   // The number of bytes required to store all registers
+};
+
+#endif  // lldb_DynamicRegisterInfo_h_
diff --git a/source/Plugins/Process/Utility/RegisterContextMemory.cpp b/source/Plugins/Process/Utility/RegisterContextMemory.cpp
new file mode 100644
index 0000000..ff077b4
--- /dev/null
+++ b/source/Plugins/Process/Utility/RegisterContextMemory.cpp
@@ -0,0 +1,158 @@
+//===-- RegisterContextMemory.cpp -------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "RegisterContextMemory.h"
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "DynamicRegisterInfo.h"
+#include "lldb/Core/DataBufferHeap.h"
+#include "lldb/Core/Error.h"
+#include "lldb/Core/RegisterValue.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Target/Thread.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+//----------------------------------------------------------------------
+// RegisterContextMemory constructor
+//----------------------------------------------------------------------
+RegisterContextMemory::RegisterContextMemory
+(
+    Thread &thread,
+    uint32_t concrete_frame_idx,
+    DynamicRegisterInfo &reg_infos,
+    addr_t reg_data_addr
+) :
+    RegisterContext (thread, concrete_frame_idx),
+    m_reg_infos (reg_infos),
+    m_reg_valid (),
+    m_reg_data (),
+    m_reg_data_addr (reg_data_addr)
+{
+    // Resize our vector of bools to contain one bool for every register.
+    // We will use these boolean values to know when a register value
+    // is valid in m_reg_data.
+    const size_t num_regs = reg_infos.GetNumRegisters();
+    assert (num_regs > 0);
+    m_reg_valid.resize (num_regs);
+
+    // Make a heap based buffer that is big enough to store all registers
+    DataBufferSP reg_data_sp(new DataBufferHeap (reg_infos.GetRegisterDataByteSize(), 0));
+    m_reg_data.SetData (reg_data_sp);
+}
+
+//----------------------------------------------------------------------
+// Destructor
+//----------------------------------------------------------------------
+RegisterContextMemory::~RegisterContextMemory()
+{
+}
+
+void
+RegisterContextMemory::InvalidateAllRegisters ()
+{
+    SetAllRegisterValid (false);
+}
+
+void
+RegisterContextMemory::SetAllRegisterValid (bool b)
+{
+    std::vector<bool>::iterator pos, end = m_reg_valid.end();
+    for (pos = m_reg_valid.begin(); pos != end; ++pos)
+        *pos = b;
+}
+
+size_t
+RegisterContextMemory::GetRegisterCount ()
+{
+    return m_reg_infos.GetNumRegisters ();
+}
+
+const RegisterInfo *
+RegisterContextMemory::GetRegisterInfoAtIndex (uint32_t reg)
+{
+    return m_reg_infos.GetRegisterInfoAtIndex (reg);
+}
+
+size_t
+RegisterContextMemory::GetRegisterSetCount ()
+{
+    return m_reg_infos.GetNumRegisterSets ();
+}
+
+const RegisterSet *
+RegisterContextMemory::GetRegisterSet (uint32_t reg_set)
+{
+    return m_reg_infos.GetRegisterSet (reg_set);
+}
+
+uint32_t
+RegisterContextMemory::ConvertRegisterKindToRegisterNumber (uint32_t kind, uint32_t num)
+{
+    return m_reg_infos.ConvertRegisterKindToRegisterNumber (kind, num);
+}
+
+bool
+RegisterContextMemory::ReadRegister (const RegisterInfo *reg_info, RegisterValue &reg_value)
+{
+    const uint32_t reg_num = reg_info->kinds[eRegisterKindLLDB];
+    if (!m_reg_valid[reg_num])
+    {                         
+        if (!ReadAllRegisterValues(m_reg_data.GetSharedDataBuffer ()))
+            return false;
+    }
+    const bool partial_data_ok = false;
+    return reg_value.SetValueFromData(reg_info, m_reg_data, reg_info->byte_offset, partial_data_ok).Success();
+}
+
+bool
+RegisterContextMemory::WriteRegister (const RegisterInfo *reg_info, const RegisterValue &reg_value)
+{
+    if (m_reg_data_addr != LLDB_INVALID_ADDRESS)
+    {
+        const uint32_t reg_num = reg_info->kinds[eRegisterKindLLDB];
+        addr_t reg_addr = m_reg_data_addr + reg_info->byte_offset;
+        Error error (WriteRegisterValueToMemory(reg_info, reg_addr, reg_info->byte_size, reg_value));
+        m_reg_valid[reg_num] = false;
+        return error.Success();
+    }
+    return false;
+}
+
+bool
+RegisterContextMemory::ReadAllRegisterValues (DataBufferSP &data_sp)
+{
+    if (m_reg_data_addr != LLDB_INVALID_ADDRESS)
+    {
+        Error error;
+        if (m_thread.GetProcess().ReadMemory(m_reg_data_addr, data_sp->GetBytes(), data_sp->GetByteSize(), error) == data_sp->GetByteSize())
+        {
+            SetAllRegisterValid (true);
+            return true;
+        }
+    }
+    return false;
+}
+
+bool
+RegisterContextMemory::WriteAllRegisterValues (const DataBufferSP &data_sp)
+{
+    if (m_reg_data_addr != LLDB_INVALID_ADDRESS)
+    {
+        Error error;
+        SetAllRegisterValid (false);
+        if (m_thread.GetProcess().WriteMemory(m_reg_data_addr, data_sp->GetBytes(), data_sp->GetByteSize(), error) == data_sp->GetByteSize())
+            return true;
+    }
+    return false;
+}
diff --git a/source/Plugins/Process/Utility/RegisterContextMemory.h b/source/Plugins/Process/Utility/RegisterContextMemory.h
new file mode 100644
index 0000000..6914e3f
--- /dev/null
+++ b/source/Plugins/Process/Utility/RegisterContextMemory.h
@@ -0,0 +1,100 @@
+//===-- RegisterContextMemory.h ---------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef lldb_RegisterContextMemory_h_
+#define lldb_RegisterContextMemory_h_
+
+// C Includes
+// C++ Includes
+#include <vector>
+
+// Other libraries and framework includes
+// Project includes
+#include "lldb/lldb-private.h"
+#include "lldb/Core/DataExtractor.h"
+#include "lldb/Target/RegisterContext.h"
+
+class DynamicRegisterInfo;
+
+class RegisterContextMemory : public lldb_private::RegisterContext
+{
+public:
+    //------------------------------------------------------------------
+    // Constructors and Destructors
+    //------------------------------------------------------------------
+    RegisterContextMemory (lldb_private::Thread &thread,
+                            uint32_t concrete_frame_idx,
+                            DynamicRegisterInfo &reg_info,
+                            lldb::addr_t reg_data_addr);
+
+    virtual
+    ~RegisterContextMemory ();
+
+    //------------------------------------------------------------------
+    // Subclasses must override these functions
+    //------------------------------------------------------------------
+    virtual void
+    InvalidateAllRegisters ();
+
+    virtual size_t
+    GetRegisterCount ();
+
+    virtual const lldb_private::RegisterInfo *
+    GetRegisterInfoAtIndex (uint32_t reg);
+
+    virtual size_t
+    GetRegisterSetCount ();
+
+    virtual const lldb_private::RegisterSet *
+    GetRegisterSet (uint32_t reg_set);
+
+    virtual uint32_t
+    ConvertRegisterKindToRegisterNumber (uint32_t kind, uint32_t num);
+
+    
+    //------------------------------------------------------------------
+    // If all of the thread register are in a contiguous buffer in 
+    // memory, then the default ReadRegister/WriteRegiter and
+    // ReadAllRegisterValues/WriteAllRegisterValues will work. If thread
+    // registers are not contiguous, clients will want to subclass this
+    // class and modify the read/write functions as needed.
+    //------------------------------------------------------------------
+
+    virtual bool
+    ReadRegister (const lldb_private::RegisterInfo *reg_info, 
+                  lldb_private::RegisterValue &reg_value);
+    
+    virtual bool
+    WriteRegister (const lldb_private::RegisterInfo *reg_info, 
+                   const lldb_private::RegisterValue &reg_value);
+    
+    virtual bool
+    ReadAllRegisterValues (lldb::DataBufferSP &data_sp);
+    
+    virtual bool
+    WriteAllRegisterValues (const lldb::DataBufferSP &data_sp);
+
+protected:
+    
+    void
+    SetAllRegisterValid (bool b);
+
+    DynamicRegisterInfo &m_reg_infos;
+    std::vector<bool> m_reg_valid;
+    lldb_private::DataExtractor m_reg_data;
+    lldb::addr_t m_reg_data_addr; // If this is valid, then we have a register context that is stored in memmory
+
+private:
+    //------------------------------------------------------------------
+    // For RegisterContextMemory only
+    //------------------------------------------------------------------
+    DISALLOW_COPY_AND_ASSIGN (RegisterContextMemory);
+};
+
+#endif  // lldb_RegisterContextMemory_h_
diff --git a/source/Plugins/Process/Utility/ThreadMemory.cpp b/source/Plugins/Process/Utility/ThreadMemory.cpp
new file mode 100644
index 0000000..95f05fd
--- /dev/null
+++ b/source/Plugins/Process/Utility/ThreadMemory.cpp
@@ -0,0 +1,112 @@
+//===-- ThreadMemory.cpp ----------------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "Plugins/Process/Utility/ThreadMemory.h"
+#include "lldb/Target/OperatingSystem.h"
+#include "lldb/Target/RegisterContext.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Target/StopInfo.h"
+#include "lldb/Target/Unwind.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+ThreadMemory::ThreadMemory (Process &process, 
+                              tid_t tid, 
+                              const ValueObjectSP &thread_info_valobj_sp) :
+    Thread (process, tid),
+    m_thread_info_valobj_sp (thread_info_valobj_sp)
+{
+}
+
+
+ThreadMemory::~ThreadMemory()
+{
+    DestroyThread();
+}
+
+bool
+ThreadMemory::WillResume (StateType resume_state)
+{
+    ClearStackFrames();
+    // Call the Thread::WillResume first. If we stop at a signal, the stop info
+    // class for signal will set the resume signal that we need below. The signal
+    // stuff obeys the Process::UnixSignal defaults. 
+    Thread::WillResume(resume_state);
+    return true;
+}
+
+RegisterContextSP
+ThreadMemory::GetRegisterContext ()
+{
+    if (!m_reg_context_sp)
+    {
+        OperatingSystem *os = m_process.GetOperatingSystem ();
+        if (os)
+            m_reg_context_sp = os->CreateRegisterContextForThread (this);
+    }
+    return m_reg_context_sp;
+}
+
+RegisterContextSP
+ThreadMemory::CreateRegisterContextForFrame (StackFrame *frame)
+{
+    RegisterContextSP reg_ctx_sp;
+    uint32_t concrete_frame_idx = 0;
+    
+    if (frame)
+        concrete_frame_idx = frame->GetConcreteFrameIndex ();
+    
+    if (concrete_frame_idx == 0)
+    {
+        reg_ctx_sp = GetRegisterContext ();
+    }
+    else if (m_unwinder_ap.get())
+    {
+        reg_ctx_sp = m_unwinder_ap->CreateRegisterContextForFrame (frame);
+    }
+    return reg_ctx_sp;
+}
+
+lldb::StopInfoSP
+ThreadMemory::GetPrivateStopReason ()
+{
+    const uint32_t process_stop_id = GetProcess().GetStopID();
+    if (m_thread_stop_reason_stop_id != process_stop_id ||
+        (m_actual_stop_info_sp && !m_actual_stop_info_sp->IsValid()))
+    {
+        // If GetGDBProcess().SetThreadStopInfo() doesn't find a stop reason
+        // for this thread, then m_actual_stop_info_sp will not ever contain
+        // a valid stop reason and the "m_actual_stop_info_sp->IsValid() == false"
+        // check will never be able to tell us if we have the correct stop info
+        // for this thread and we will continually send qThreadStopInfo packets
+        // down to the remote GDB server, so we need to keep our own notion
+        // of the stop ID that m_actual_stop_info_sp is valid for (even if it
+        // contains nothing). We use m_thread_stop_reason_stop_id for this below.
+        m_thread_stop_reason_stop_id = process_stop_id;
+        m_actual_stop_info_sp.reset();
+        
+        OperatingSystem *os = m_process.GetOperatingSystem ();
+        if (os)
+            m_actual_stop_info_sp = os->CreateThreadStopReason (this);
+    }
+    return m_actual_stop_info_sp;
+    
+}
+
+void
+ThreadMemory::RefreshStateAfterStop()
+{
+    RegisterContextSP reg_ctx_sp(GetRegisterContext());
+    if (reg_ctx_sp)
+    {
+        const bool force = true;
+        reg_ctx_sp->InvalidateIfNeeded (force);
+    }
+}
diff --git a/source/Plugins/Process/Utility/ThreadMemory.h b/source/Plugins/Process/Utility/ThreadMemory.h
new file mode 100644
index 0000000..93cc255
--- /dev/null
+++ b/source/Plugins/Process/Utility/ThreadMemory.h
@@ -0,0 +1,64 @@
+//===-- ThreadMemory.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_ThreadMemory_h_
+#define liblldb_ThreadMemory_h_
+
+#include "lldb/Target/Thread.h"
+
+class ThreadMemory :
+    public lldb_private::Thread
+{
+public:
+
+    ThreadMemory (lldb_private::Process &process, 
+                   lldb::tid_t tid,
+                   const lldb::ValueObjectSP &thread_info_valobj_sp);
+
+    virtual 
+    ~ThreadMemory();
+
+    //------------------------------------------------------------------
+    // lldb_private::Thread methods
+    //------------------------------------------------------------------
+    virtual void
+    RefreshStateAfterStop();
+
+    virtual lldb::RegisterContextSP
+    GetRegisterContext ();
+
+    virtual lldb::RegisterContextSP
+    CreateRegisterContextForFrame (lldb_private::StackFrame *frame);
+
+    virtual lldb::StopInfoSP
+    GetPrivateStopReason ();
+
+    virtual bool
+    WillResume (lldb::StateType resume_state);
+
+    lldb::ValueObjectSP &
+    GetValueObject ()
+    {
+        return m_thread_info_valobj_sp;
+    }
+
+protected:
+    //------------------------------------------------------------------
+    // For ThreadMemory and subclasses
+    //------------------------------------------------------------------
+    lldb::ValueObjectSP m_thread_info_valobj_sp;
+    
+private:
+    //------------------------------------------------------------------
+    // For ThreadMemory only
+    //------------------------------------------------------------------
+    DISALLOW_COPY_AND_ASSIGN (ThreadMemory);
+};
+
+#endif  // liblldb_ThreadMemory_h_
diff --git a/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp b/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
index 558a02a..0c02ff6 100644
--- a/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
+++ b/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
@@ -390,7 +390,7 @@
     {
         // We have a valid process
         SetID (pid);
-        UpdateThreadListIfNeeded ();
+        GetThreadList();
         if (m_gdb_comm.SendPacketAndWaitForResponse("?", 1, m_last_stop_packet, false))
         {
             const StateType state = SetThreadStopInfo (m_last_stop_packet);
@@ -1062,43 +1062,32 @@
 }
 
 uint32_t
-ProcessGDBRemote::UpdateThreadListIfNeeded ()
+ProcessGDBRemote::UpdateThreadList (ThreadList &old_thread_list, ThreadList &new_thread_list)
 {
     // locker will keep a mutex locked until it goes out of scope
     LogSP log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_THREAD));
     if (log && log->GetMask().Test(GDBR_LOG_VERBOSE))
         log->Printf ("ProcessGDBRemote::%s (pid = %i)", __FUNCTION__, GetID());
+    // Update the thread list's stop id immediately so we don't recurse into this function.
 
-    Mutex::Locker locker (m_thread_list.GetMutex ());
-    const uint32_t stop_id = GetStopID();
-    if (m_thread_list.GetSize(false) == 0 || stop_id != m_thread_list.GetStopID())
+    std::vector<lldb::tid_t> thread_ids;
+    bool sequence_mutex_unavailable = false;
+    const size_t num_thread_ids = m_gdb_comm.GetCurrentThreadIDs (thread_ids, sequence_mutex_unavailable);
+    if (num_thread_ids > 0)
     {
-        // Update the thread list's stop id immediately so we don't recurse into this function.
-        ThreadList curr_thread_list (this);
-        curr_thread_list.SetStopID(stop_id);
-
-        std::vector<lldb::tid_t> thread_ids;
-        bool sequence_mutex_unavailable = false;
-        const size_t num_thread_ids = m_gdb_comm.GetCurrentThreadIDs (thread_ids, sequence_mutex_unavailable);
-        if (num_thread_ids > 0)
+        for (size_t i=0; i<num_thread_ids; ++i)
         {
-            for (size_t i=0; i<num_thread_ids; ++i)
-            {
-                tid_t tid = thread_ids[i];
-                ThreadSP thread_sp (GetThreadList().FindThreadByID (tid, false));
-                if (!thread_sp)
-                    thread_sp.reset (new ThreadGDBRemote (*this, tid));
-                curr_thread_list.AddThread(thread_sp);
-            }
-        }
-
-        if (sequence_mutex_unavailable == false)
-        {
-            m_thread_list = curr_thread_list;
-            SetThreadStopInfo (m_last_stop_packet);
+            tid_t tid = thread_ids[i];
+            ThreadSP thread_sp (old_thread_list.FindThreadByID (tid, false));
+            if (!thread_sp)
+                thread_sp.reset (new ThreadGDBRemote (*this, tid));
+            new_thread_list.AddThread(thread_sp);
         }
     }
-    return GetThreadList().GetSize(false);
+
+    if (sequence_mutex_unavailable == false)
+        SetThreadStopInfo (m_last_stop_packet);
+    return new_thread_list.GetSize(false);
 }
 
 
@@ -1318,7 +1307,7 @@
                             }
                         }
                         if (!handled)
-                    gdb_thread->SetStopInfo (StopInfo::CreateStopReasonWithSignal (*thread_sp, signo));
+                            gdb_thread->SetStopInfo (StopInfo::CreateStopReasonWithSignal (*thread_sp, signo));
                 }
                 else
                 {
diff --git a/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h b/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h
index 4f4f7fb..886eb60 100644
--- a/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h
+++ b/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h
@@ -267,7 +267,8 @@
     }
 
     uint32_t
-    UpdateThreadListIfNeeded ();
+    UpdateThreadList (lldb_private::ThreadList &old_thread_list, 
+                      lldb_private::ThreadList &new_thread_list);
 
     lldb_private::Error
     StartDebugserverProcess (const char *debugserver_url);
diff --git a/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp b/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp
index 0be5edf..23a71f1 100644
--- a/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp
+++ b/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp
@@ -23,13 +23,8 @@
 
 #include "ProcessGDBRemote.h"
 #include "ProcessGDBRemoteLog.h"
-#include "Plugins/Process/Utility/UnwindLLDB.h"
 #include "Utility/StringExtractorGDBRemote.h"
 
-#if defined(__APPLE__)
-#include "UnwindMacOSXFrameBackchain.h"
-#endif
-
 using namespace lldb;
 using namespace lldb_private;
 
@@ -52,14 +47,6 @@
     DestroyThread();
 }
 
-
-const char *
-ThreadGDBRemote::GetInfo ()
-{
-    return NULL;
-}
-
-
 const char *
 ThreadGDBRemote::GetName ()
 {
@@ -135,32 +122,6 @@
     GetRegisterContext()->InvalidateIfNeeded (force);
 }
 
-Unwind *
-ThreadGDBRemote::GetUnwinder ()
-{
-    if (m_unwinder_ap.get() == NULL)
-    {
-        const ArchSpec target_arch (GetProcess().GetTarget().GetArchitecture ());
-        const llvm::Triple::ArchType machine = target_arch.GetMachine();
-        switch (machine)
-        {
-            case llvm::Triple::x86_64:
-            case llvm::Triple::x86:
-            case llvm::Triple::arm:
-            case llvm::Triple::thumb:
-                m_unwinder_ap.reset (new UnwindLLDB (*this));
-                break;
-
-            default:
-#if defined(__APPLE__)
-                m_unwinder_ap.reset (new UnwindMacOSXFrameBackchain (*this));
-#endif
-                break;
-        }
-    }
-    return m_unwinder_ap.get();
-}
-
 void
 ThreadGDBRemote::ClearStackFrames ()
 {
diff --git a/source/Plugins/Process/gdb-remote/ThreadGDBRemote.h b/source/Plugins/Process/gdb-remote/ThreadGDBRemote.h
index 2fdb4d7..09f8684 100644
--- a/source/Plugins/Process/gdb-remote/ThreadGDBRemote.h
+++ b/source/Plugins/Process/gdb-remote/ThreadGDBRemote.h
@@ -33,9 +33,6 @@
     RefreshStateAfterStop();
 
     virtual const char *
-    GetInfo ();
-
-    virtual const char *
     GetName ();
 
     virtual const char *
@@ -113,9 +110,6 @@
     // Member variables.
     //------------------------------------------------------------------
 
-    virtual lldb_private::Unwind *
-    GetUnwinder ();
-
     void
     SetStopInfoFromPacket (StringExtractor &stop_packet, uint32_t stop_id);